Tizen 2.0 Release
[profile/ivi/osmesa.git] / src / mesa / math / m_debug_norm.c
1
2 /*
3  * Mesa 3-D graphics library
4  * Version:  5.1
5  *
6  * Copyright (C) 1999-2003  Brian Paul   All Rights Reserved.
7  *
8  * Permission is hereby granted, free of charge, to any person obtaining a
9  * copy of this software and associated documentation files (the "Software"),
10  * to deal in the Software without restriction, including without limitation
11  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12  * and/or sell copies of the Software, and to permit persons to whom the
13  * Software is furnished to do so, subject to the following conditions:
14  *
15  * The above copyright notice and this permission notice shall be included
16  * in all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
21  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24  *
25  * Authors:
26  *    Gareth Hughes
27  */
28
29 #include "main/glheader.h"
30 #include "main/context.h"
31 #include "main/macros.h"
32 #include "main/imports.h"
33
34 #include "m_matrix.h"
35 #include "m_xform.h"
36
37 #include "m_debug.h"
38 #include "m_debug_util.h"
39
40
41 #ifdef __UNIXOS2__
42 /* The linker doesn't like empty files */
43 static char dummy;
44 #endif
45
46 #ifdef DEBUG_MATH  /* This code only used for debugging */
47
48
49 static int m_norm_identity[16] = {
50    ONE, NIL, NIL, NIL,
51    NIL, ONE, NIL, NIL,
52    NIL, NIL, ONE, NIL,
53    NIL, NIL, NIL, NIL
54 };
55 static int m_norm_general[16] = {
56    VAR, VAR, VAR, NIL,
57    VAR, VAR, VAR, NIL,
58    VAR, VAR, VAR, NIL,
59    NIL, NIL, NIL, NIL
60 };
61 static int m_norm_no_rot[16] = {
62    VAR, NIL, NIL, NIL,
63    NIL, VAR, NIL, NIL,
64    NIL, NIL, VAR, NIL,
65    NIL, NIL, NIL, NIL
66 };
67 static int *norm_templates[8] = {
68    m_norm_no_rot,
69    m_norm_no_rot,
70    m_norm_no_rot,
71    m_norm_general,
72    m_norm_general,
73    m_norm_general,
74    m_norm_identity,
75    m_norm_identity
76 };
77 static int norm_types[8] = {
78    NORM_TRANSFORM_NO_ROT,
79    NORM_TRANSFORM_NO_ROT | NORM_RESCALE,
80    NORM_TRANSFORM_NO_ROT | NORM_NORMALIZE,
81    NORM_TRANSFORM,
82    NORM_TRANSFORM | NORM_RESCALE,
83    NORM_TRANSFORM | NORM_NORMALIZE,
84    NORM_RESCALE,
85    NORM_NORMALIZE
86 };
87 static int norm_scale_types[8] = {               /*  rescale factor          */
88    NIL,                                          /*  NIL disables rescaling  */
89    VAR,
90    NIL,
91    NIL,
92    VAR,
93    NIL,
94    VAR,
95    NIL
96 };
97 static int norm_normalize_types[8] = {           /*  normalizing ?? (no = 0) */
98    0,
99    0,
100    1,
101    0,
102    0,
103    1,
104    0,
105    1
106 };
107 static char *norm_strings[8] = {
108    "NORM_TRANSFORM_NO_ROT",
109    "NORM_TRANSFORM_NO_ROT | NORM_RESCALE",
110    "NORM_TRANSFORM_NO_ROT | NORM_NORMALIZE",
111    "NORM_TRANSFORM",
112    "NORM_TRANSFORM | NORM_RESCALE",
113    "NORM_TRANSFORM | NORM_NORMALIZE",
114    "NORM_RESCALE",
115    "NORM_NORMALIZE"
116 };
117
118
119 /* =============================================================
120  * Reference transformations
121  */
122
123 static void ref_norm_transform_rescale( const GLmatrix *mat,
124                                         GLfloat scale,
125                                         const GLvector4f *in,
126                                         const GLfloat *lengths,
127                                         GLvector4f *dest )
128 {
129    GLuint i;
130    const GLfloat *s = in->start;
131    const GLfloat *m = mat->inv;
132    GLfloat (*out)[4] = (GLfloat (*)[4]) dest->start;
133
134    (void) lengths;
135
136    for ( i = 0 ; i < in->count ; i++ ) {
137       GLfloat t[3];
138
139       TRANSFORM_NORMAL( t, s, m );
140       SCALE_SCALAR_3V( out[i], scale, t );
141
142       s = (GLfloat *)((char *)s + in->stride);
143    }
144 }
145
146 static void ref_norm_transform_normalize( const GLmatrix *mat,
147                                           GLfloat scale,
148                                           const GLvector4f *in,
149                                           const GLfloat *lengths,
150                                           GLvector4f *dest )
151 {
152    GLuint i;
153    const GLfloat *s = in->start;
154    const GLfloat *m = mat->inv;
155    GLfloat (*out)[4] = (GLfloat (*)[4]) dest->start;
156
157    for ( i = 0 ; i < in->count ; i++ ) {
158       GLfloat t[3];
159
160       TRANSFORM_NORMAL( t, s, m );
161
162       if ( !lengths ) {
163          GLfloat len = LEN_SQUARED_3FV( t );
164          if ( len > 1e-20 ) {
165             /* Hmmm, don't know how we could test the precalculated
166              * length case...
167              */
168             scale = 1.0 / SQRTF( len );
169             SCALE_SCALAR_3V( out[i], scale, t );
170          } else {
171             out[i][0] = out[i][1] = out[i][2] = 0;
172          }
173       } else {
174          scale = lengths[i];;
175          SCALE_SCALAR_3V( out[i], scale, t );
176       }
177
178       s = (GLfloat *)((char *)s + in->stride);
179    }
180 }
181
182
183 /* =============================================================
184  * Normal transformation tests
185  */
186
187 static void init_matrix( GLfloat *m )
188 {
189    m[0] = 63.0; m[4] = 43.0; m[ 8] = 29.0; m[12] = 43.0;
190    m[1] = 55.0; m[5] = 17.0; m[ 9] = 31.0; m[13] =  7.0;
191    m[2] = 44.0; m[6] =  9.0; m[10] =  7.0; m[14] =  3.0;
192    m[3] = 11.0; m[7] = 23.0; m[11] = 91.0; m[15] =  9.0;
193 }
194
195
196 static int test_norm_function( normal_func func, int mtype, long *cycles )
197 {
198    GLvector4f source[1], dest[1], dest2[1], ref[1], ref2[1];
199    GLmatrix mat[1];
200    GLfloat s[TEST_COUNT][5], d[TEST_COUNT][4], r[TEST_COUNT][4];
201    GLfloat d2[TEST_COUNT][4], r2[TEST_COUNT][4], length[TEST_COUNT];
202    GLfloat scale;
203    GLfloat *m;
204    int i, j;
205 #ifdef  RUN_DEBUG_BENCHMARK
206    int cycle_i;         /* the counter for the benchmarks we run */
207 #endif
208
209    (void) cycles;
210
211    mat->m = (GLfloat *) _mesa_align_malloc( 16 * sizeof(GLfloat), 16 );
212    mat->inv = m = mat->m;
213
214    init_matrix( m );
215
216    scale = 1.0F + rnd () * norm_scale_types[mtype];
217
218    for ( i = 0 ; i < 4 ; i++ ) {
219       for ( j = 0 ; j < 4 ; j++ ) {
220          switch ( norm_templates[mtype][i * 4 + j] ) {
221          case NIL:
222             m[j * 4 + i] = 0.0;
223             break;
224          case ONE:
225             m[j * 4 + i] = 1.0;
226             break;
227          case NEG:
228             m[j * 4 + i] = -1.0;
229             break;
230          case VAR:
231             break;
232          default:
233             exit(1);
234          }
235       }
236    }
237
238    for ( i = 0 ; i < TEST_COUNT ; i++ ) {
239       ASSIGN_3V( d[i],  0.0, 0.0, 0.0 );
240       ASSIGN_3V( s[i],  0.0, 0.0, 0.0 );
241       ASSIGN_3V( d2[i], 0.0, 0.0, 0.0 );
242       for ( j = 0 ; j < 3 ; j++ )
243          s[i][j] = rnd();
244       length[i] = 1 / SQRTF( LEN_SQUARED_3FV( s[i] ) );
245    }
246
247    source->data = (GLfloat(*)[4]) s;
248    source->start = (GLfloat *) s;
249    source->count = TEST_COUNT;
250    source->stride = sizeof(s[0]);
251    source->flags = 0;
252
253    dest->data = d;
254    dest->start = (GLfloat *) d;
255    dest->count = TEST_COUNT;
256    dest->stride = sizeof(float[4]);
257    dest->flags = 0;
258
259    dest2->data = d2;
260    dest2->start = (GLfloat *) d2;
261    dest2->count = TEST_COUNT;
262    dest2->stride = sizeof(float[4]);
263    dest2->flags = 0;
264
265    ref->data = r;
266    ref->start = (GLfloat *) r;
267    ref->count = TEST_COUNT;
268    ref->stride = sizeof(float[4]);
269    ref->flags = 0;
270
271    ref2->data = r2;
272    ref2->start = (GLfloat *) r2;
273    ref2->count = TEST_COUNT;
274    ref2->stride = sizeof(float[4]);
275    ref2->flags = 0;
276
277    if ( norm_normalize_types[mtype] == 0 ) {
278       ref_norm_transform_rescale( mat, scale, source, NULL, ref );
279    } else {
280       ref_norm_transform_normalize( mat, scale, source, NULL, ref );
281       ref_norm_transform_normalize( mat, scale, source, length, ref2 );
282    }
283
284    if ( mesa_profile ) {
285       BEGIN_RACE( *cycles );
286       func( mat, scale, source, NULL, dest );
287       END_RACE( *cycles );
288       func( mat, scale, source, length, dest2 );
289    } else {
290       func( mat, scale, source, NULL, dest );
291       func( mat, scale, source, length, dest2 );
292    }
293
294    for ( i = 0 ; i < TEST_COUNT ; i++ ) {
295       for ( j = 0 ; j < 3 ; j++ ) {
296          if ( significand_match( d[i][j], r[i][j] ) < REQUIRED_PRECISION ) {
297             printf( "-----------------------------\n" );
298             printf( "(i = %i, j = %i)\n", i, j );
299             printf( "%f \t %f \t [ratio = %e - %i bit missed]\n",
300                     d[i][0], r[i][0], r[i][0]/d[i][0],
301                     MAX_PRECISION - significand_match( d[i][0], r[i][0] ) );
302             printf( "%f \t %f \t [ratio = %e - %i bit missed]\n",
303                     d[i][1], r[i][1], r[i][1]/d[i][1],
304                     MAX_PRECISION - significand_match( d[i][1], r[i][1] ) );
305             printf( "%f \t %f \t [ratio = %e - %i bit missed]\n",
306                     d[i][2], r[i][2], r[i][2]/d[i][2],
307                     MAX_PRECISION - significand_match( d[i][2], r[i][2] ) );
308             return 0;
309          }
310
311          if ( norm_normalize_types[mtype] != 0 ) {
312             if ( significand_match( d2[i][j], r2[i][j] ) < REQUIRED_PRECISION ) {
313                printf( "------------------- precalculated length case ------\n" );
314                printf( "(i = %i, j = %i)\n", i, j );
315                printf( "%f \t %f \t [ratio = %e - %i bit missed]\n",
316                        d2[i][0], r2[i][0], r2[i][0]/d2[i][0],
317                        MAX_PRECISION - significand_match( d2[i][0], r2[i][0] ) );
318                printf( "%f \t %f \t [ratio = %e - %i bit missed]\n",
319                        d2[i][1], r2[i][1], r2[i][1]/d2[i][1],
320                        MAX_PRECISION - significand_match( d2[i][1], r2[i][1] ) );
321                printf( "%f \t %f \t [ratio = %e - %i bit missed]\n",
322                        d2[i][2], r2[i][2], r2[i][2]/d2[i][2],
323                        MAX_PRECISION - significand_match( d2[i][2], r2[i][2] ) );
324                return 0;
325             }
326          }
327       }
328    }
329
330    _mesa_align_free( mat->m );
331    return 1;
332 }
333
334 void _math_test_all_normal_transform_functions( char *description )
335 {
336    int mtype;
337    long benchmark_tab[0xf];
338    static int first_time = 1;
339
340    if ( first_time ) {
341       first_time = 0;
342       mesa_profile = _mesa_getenv( "MESA_PROFILE" );
343    }
344
345 #ifdef RUN_DEBUG_BENCHMARK
346    if ( mesa_profile ) {
347       if ( !counter_overhead ) {
348          INIT_COUNTER();
349          printf( "counter overhead: %ld cycles\n\n", counter_overhead );
350       }
351       printf( "normal transform results after hooking in %s functions:\n",
352               description );
353       printf( "\n-------------------------------------------------------\n" );
354    }
355 #endif
356
357    for ( mtype = 0 ; mtype < 8 ; mtype++ ) {
358       normal_func func = _mesa_normal_tab[norm_types[mtype]];
359       long *cycles = &benchmark_tab[mtype];
360
361       if ( test_norm_function( func, mtype, cycles ) == 0 ) {
362          char buf[100];
363          sprintf( buf, "_mesa_normal_tab[0][%s] failed test (%s)",
364                   norm_strings[mtype], description );
365          _mesa_problem( NULL, "%s", buf );
366       }
367
368 #ifdef RUN_DEBUG_BENCHMARK
369       if ( mesa_profile ) {
370          printf( " %li\t", benchmark_tab[mtype] );
371          printf( " | [%s]\n", norm_strings[mtype] );
372       }
373 #endif
374    }
375 #ifdef RUN_DEBUG_BENCHMARK
376    if ( mesa_profile ) {
377       printf( "\n" );
378    }
379 #endif
380 }
381
382
383 #endif /* DEBUG_MATH */