]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - dense-linear-algebra-libraries/linalg.git/blob - blis/testsuite/src/test_randm.c
cef126d4c5cafa86715ba58de01d3308c4aff23e
[dense-linear-algebra-libraries/linalg.git] / blis / testsuite / src / test_randm.c
1 /*
3    BLIS    
4    An object-based framework for developing high-performance BLAS-like
5    libraries.
7    Copyright (C) 2014, The University of Texas at Austin
9    Redistribution and use in source and binary forms, with or without
10    modification, are permitted provided that the following conditions are
11    met:
12     - Redistributions of source code must retain the above copyright
13       notice, this list of conditions and the following disclaimer.
14     - Redistributions in binary form must reproduce the above copyright
15       notice, this list of conditions and the following disclaimer in the
16       documentation and/or other materials provided with the distribution.
17     - Neither the name of The University of Texas at Austin nor the names
18       of its contributors may be used to endorse or promote products
19       derived from this software without specific prior written permission.
21    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25    HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
35 #include "blis.h"
36 #include "test_libblis.h"
39 // Static variables.
40 static char*     op_str                    = "randm";
41 static char*     o_types                   = "m";  // a
42 static char*     p_types                   = "";   // (no parameters)
43 static thresh_t  thresh[BLIS_NUM_FP_TYPES] = { { 1e-04, 1e-05 },   // warn, pass for s
44                                                { 1e-04, 1e-05 },   // warn, pass for c
45                                                { 1e-13, 1e-14 },   // warn, pass for d
46                                                { 1e-13, 1e-14 } }; // warn, pass for z
48 // Local prototypes.
49 void libblis_test_randm_deps( test_params_t* params,
50                               test_op_t*     op );
52 void libblis_test_randm_experiment( test_params_t* params,
53                                     test_op_t*     op,
54                                     iface_t        iface,
55                                     num_t          datatype,
56                                     char*          pc_str,
57                                     char*          sc_str,
58                                     unsigned int   p_cur,
59                                     double*        perf,
60                                     double*        resid );
62 void libblis_test_randm_impl( iface_t   iface,
63                               obj_t*    x );
65 void libblis_test_randm_check( obj_t*  x,
66                                double* resid );
70 void libblis_test_randm_deps( test_params_t* params, test_op_t* op )
71 {
72         // No dependencies.
73 }
77 void libblis_test_randm( test_params_t* params, test_op_t* op )
78 {
80         // Return early if this test has already been done.
81         if ( op->test_done == TRUE ) return;
83         // Return early if operation is disabled.
84         if ( op->op_switch == DISABLE_ALL ||
85              op->ops->util_over == DISABLE_ALL ) return;
87         // Call dependencies first.
88         if ( TRUE ) libblis_test_randm_deps( params, op );
90         // Execute the test driver for each implementation requested.
91         if ( op->front_seq == ENABLE )
92         {
93                 libblis_test_op_driver( params,
94                                         op,
95                                         BLIS_TEST_SEQ_FRONT_END,
96                                         op_str,
97                                         p_types,
98                                         o_types,
99                                         thresh,
100                                         libblis_test_randm_experiment );
101         }
106 void libblis_test_randm_experiment( test_params_t* params,
107                                     test_op_t*     op,
108                                     iface_t        iface,
109                                     num_t          dt,
110                                     char*          pc_str,
111                                     char*          sc_str,
112                                     unsigned int   p_cur,
113                                     double*        perf,
114                                     double*        resid )
116         unsigned int n_repeats = params->n_repeats;
117         unsigned int i;
119         double       time_min  = 1e9;
120         double       time;
122         dim_t        m, n;
124         char         x_store;
126         obj_t        x;
129         // Map the dimension specifier to actual dimensions.
130         m = libblis_test_get_dim_from_prob_size( op->dim_spec[0], p_cur );
131         n = libblis_test_get_dim_from_prob_size( op->dim_spec[1], p_cur );
133         // Map parameter characters to BLIS constants.
135         // Extract the storage character for each operand.
136         x_store = sc_str[0];
138         // Create the test objects.
139         libblis_test_mobj_create( params, dt, BLIS_NO_TRANSPOSE, x_store, m, n, &x );
141         // Repeat the experiment n_repeats times and record results. 
142         for ( i = 0; i < n_repeats; ++i )
143         {
144                 time = bli_clock();
146                 libblis_test_randm_impl( iface, &x );
148                 time_min = bli_clock_min_diff( time_min, time );
149         }
151         // Estimate the performance of the best experiment repeat.
152         *perf = ( 2.0 * m * n ) / time_min / FLOPS_PER_UNIT_PERF;
153         if ( bli_obj_is_complex( x ) ) *perf *= 2.0;
155         // Perform checks.
156         // For randm(), we don't return a meaningful residual/diff, since we can't
157         // really say for sure what is "random" and what is not, so instead we
158         // manually perform some checks that will fail under some scenarios whic
159         // we consider to be likely.
160         libblis_test_randm_check( &x, resid );
162         // Zero out performance and residual if input matrix is empty.
163         libblis_test_check_empty_problem( &x, perf, resid );
165         // Free the test objects.
166         bli_obj_free( &x );
171 void libblis_test_randm_impl( iface_t   iface,
172                               obj_t*    x )
174         switch ( iface )
175         {
176                 case BLIS_TEST_SEQ_FRONT_END:
177                 bli_randm( x );
178                 break;
180                 default:
181                 libblis_test_printf_error( "Invalid interface type.\n" );
182         }
187 void libblis_test_randm_check( obj_t*  x,
188                                double* resid )
190         num_t  dt_real = bli_obj_datatype_proj_to_real( *x );
191         dim_t  m_x     = bli_obj_length( *x );
192         dim_t  n_x     = bli_obj_width( *x );
193         obj_t  sum;
195         //
196         // The two most likely ways that randm would fail is if all elements
197         // were zero, or if all elements were greater than or equal to one.
198         // We check both of these conditions by computing the sum of the
199         // absolute values of the elements of x.
200         //
202         *resid = 0.0;
204         bli_obj_scalar_init_detached( dt_real, &sum );
206         bli_absumm( x, &sum );
207         
208         if ( bli_is_float( dt_real ) )
209         {
210                 float*  sum_x = bli_obj_buffer_at_off( sum );
212                 if      ( *sum_x == *bli_d0         ) *resid = 1.0;
213                 else if ( *sum_x >= 2.0 * m_x * n_x ) *resid = 2.0;
214         }
215         else // if ( bli_is_double( dt_real ) )
216         {
217                 double* sum_x = bli_obj_buffer_at_off( sum );
219                 if      ( *sum_x == *bli_d0         ) *resid = 1.0;
220                 else if ( *sum_x >= 2.0 * m_x * n_x ) *resid = 2.0;
221         }
227 #define FUNCPTR_T absumm_fp
229 typedef void (*FUNCPTR_T)(
230                            dim_t  m,
231                            dim_t  n,
232                            void*  x, inc_t rs_x, inc_t cs_x,
233                            void*  sum_x
234                          );
236 static FUNCPTR_T GENARRAY(ftypes,absumm);
239 void bli_absumm( obj_t*  x,
240                  obj_t*  sum_x )
242         num_t     dt        = bli_obj_datatype( *x );
244         dim_t     m         = bli_obj_length( *x );
245         dim_t     n         = bli_obj_width( *x );
247         void*     buf_x     = bli_obj_buffer_at_off( *x );
248         inc_t     rs_x      = bli_obj_row_stride( *x );
249         inc_t     cs_x      = bli_obj_col_stride( *x );
251         void*     buf_sum_x = bli_obj_buffer_at_off( *sum_x );
253         FUNCPTR_T f;
256         // Index into the type combination array to extract the correct
257         // function pointer.
258         f = ftypes[dt];
260         // Invoke the function.
261         f( m,
262            n,
263            buf_x, rs_x, cs_x,
264            buf_sum_x );
268 #undef  GENTFUNCR
269 #define GENTFUNCR( ctype, ctype_r, ch, chr, varname ) \
271 void PASTEMAC(ch,varname)( \
272                            dim_t  m, \
273                            dim_t  n, \
274                            void*  x, inc_t rs_x, inc_t cs_x, \
275                            void*  sum_x  \
276                          ) \
277 { \
278         ctype*   x_cast     = x; \
279         ctype_r* sum_x_cast = sum_x; \
280         ctype_r  abs_chi1; \
281         ctype_r  sum; \
282         dim_t    i, j; \
284         PASTEMAC(chr,set0s)( sum ); \
286         for ( j = 0; j < n; j++ ) \
287         { \
288                 for ( i = 0; i < m; i++ ) \
289                 { \
290                         ctype* chi1 = x_cast + (i  )*rs_x + (j  )*cs_x; \
292                         PASTEMAC2(ch,chr,abval2s)( *chi1, abs_chi1 ); \
293                         PASTEMAC2(chr,chr,adds)( abs_chi1, sum ); \
294                 } \
295         } \
297         PASTEMAC2(chr,chr,copys)( sum, *sum_x_cast ); \
300 INSERT_GENTFUNCR_BASIC0( absumm )