Subversion Repositories shark

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

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