Killed mmath.[ch]. Moved low-level functions/assembly code into imports.[ch]
[mesa.git] / src / mesa / math / m_debug_norm.c
1 /* $Id: m_debug_norm.c,v 1.13 2003/03/01 01:50:24 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 5.1
6 *
7 * Copyright (C) 1999-2003 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
35 #include "m_matrix.h"
36 #include "m_xform.h"
37
38 #include "m_debug.h"
39 #include "m_debug_util.h"
40
41
42 #ifdef DEBUG /* This code only used for debugging */
43
44
45 static int m_norm_identity[16] = {
46 ONE, NIL, NIL, NIL,
47 NIL, ONE, NIL, NIL,
48 NIL, NIL, ONE, NIL,
49 NIL, NIL, NIL, NIL
50 };
51 static int m_norm_general[16] = {
52 VAR, VAR, VAR, NIL,
53 VAR, VAR, VAR, NIL,
54 VAR, VAR, VAR, NIL,
55 NIL, NIL, NIL, NIL
56 };
57 static int m_norm_no_rot[16] = {
58 VAR, NIL, NIL, NIL,
59 NIL, VAR, NIL, NIL,
60 NIL, NIL, VAR, NIL,
61 NIL, NIL, NIL, NIL
62 };
63 static int *norm_templates[8] = {
64 m_norm_no_rot,
65 m_norm_no_rot,
66 m_norm_no_rot,
67 m_norm_general,
68 m_norm_general,
69 m_norm_general,
70 m_norm_identity,
71 m_norm_identity
72 };
73 static int norm_types[8] = {
74 NORM_TRANSFORM_NO_ROT,
75 NORM_TRANSFORM_NO_ROT | NORM_RESCALE,
76 NORM_TRANSFORM_NO_ROT | NORM_NORMALIZE,
77 NORM_TRANSFORM,
78 NORM_TRANSFORM | NORM_RESCALE,
79 NORM_TRANSFORM | NORM_NORMALIZE,
80 NORM_RESCALE,
81 NORM_NORMALIZE
82 };
83 static int norm_scale_types[8] = { /* rescale factor */
84 NIL, /* NIL disables rescaling */
85 VAR,
86 NIL,
87 NIL,
88 VAR,
89 NIL,
90 VAR,
91 NIL
92 };
93 static int norm_normalize_types[8] = { /* normalizing ?? (no = 0) */
94 0,
95 0,
96 1,
97 0,
98 0,
99 1,
100 0,
101 1
102 };
103 static char *norm_strings[8] = {
104 "NORM_TRANSFORM_NO_ROT",
105 "NORM_TRANSFORM_NO_ROT | NORM_RESCALE",
106 "NORM_TRANSFORM_NO_ROT | NORM_NORMALIZE",
107 "NORM_TRANSFORM",
108 "NORM_TRANSFORM | NORM_RESCALE",
109 "NORM_TRANSFORM | NORM_NORMALIZE",
110 "NORM_RESCALE",
111 "NORM_NORMALIZE"
112 };
113
114
115 /* =============================================================
116 * Reference transformations
117 */
118
119 static void ref_norm_transform_rescale( const GLmatrix *mat,
120 GLfloat scale,
121 const GLvector4f *in,
122 const GLfloat *lengths,
123 GLvector4f *dest )
124 {
125 GLuint i;
126 const GLfloat *s = in->start;
127 const GLfloat *m = mat->inv;
128 GLfloat (*out)[4] = (GLfloat (*)[4]) dest->start;
129
130 (void) lengths;
131
132 for ( i = 0 ; i < in->count ; i++ ) {
133 GLfloat t[3];
134
135 TRANSFORM_NORMAL( t, s, m );
136 SCALE_SCALAR_3V( out[i], scale, t );
137
138 s = (GLfloat *)((char *)s + in->stride);
139 }
140 }
141
142 static void ref_norm_transform_normalize( const GLmatrix *mat,
143 GLfloat scale,
144 const GLvector4f *in,
145 const GLfloat *lengths,
146 GLvector4f *dest )
147 {
148 GLuint i;
149 const GLfloat *s = in->start;
150 const GLfloat *m = mat->inv;
151 GLfloat (*out)[4] = (GLfloat (*)[4]) dest->start;
152
153 for ( i = 0 ; i < in->count ; i++ ) {
154 GLfloat t[3];
155
156 TRANSFORM_NORMAL( t, s, m );
157
158 if ( !lengths ) {
159 GLfloat len = LEN_SQUARED_3FV( t );
160 if ( len > 1e-20 ) {
161 /* Hmmm, don't know how we could test the precalculated
162 * length case...
163 */
164 scale = 1.0 / sqrt( len );
165 SCALE_SCALAR_3V( out[i], scale, t );
166 } else {
167 out[i][0] = out[i][1] = out[i][2] = 0;
168 }
169 } else {
170 scale = lengths[i];;
171 SCALE_SCALAR_3V( out[i], scale, t );
172 }
173
174 s = (GLfloat *)((char *)s + in->stride);
175 }
176 }
177
178
179 /* =============================================================
180 * Normal transformation tests
181 */
182
183 static void init_matrix( GLfloat *m )
184 {
185 m[0] = 63.0; m[4] = 43.0; m[ 8] = 29.0; m[12] = 43.0;
186 m[1] = 55.0; m[5] = 17.0; m[ 9] = 31.0; m[13] = 7.0;
187 m[2] = 44.0; m[6] = 9.0; m[10] = 7.0; m[14] = 3.0;
188 m[3] = 11.0; m[7] = 23.0; m[11] = 91.0; m[15] = 9.0;
189 }
190
191
192 static int test_norm_function( normal_func func, int mtype, long *cycles )
193 {
194 GLvector4f source[1], dest[1], dest2[1], ref[1], ref2[1];
195 GLmatrix mat[1];
196 GLfloat s[TEST_COUNT][5], d[TEST_COUNT][4], r[TEST_COUNT][4];
197 GLfloat d2[TEST_COUNT][4], r2[TEST_COUNT][4], length[TEST_COUNT];
198 GLfloat scale;
199 GLfloat *m;
200 int i, j;
201 #ifdef RUN_DEBUG_BENCHMARK
202 int cycle_i; /* the counter for the benchmarks we run */
203 #endif
204
205 (void) cycles;
206
207 mat->m = (GLfloat *) ALIGN_MALLOC( 16 * sizeof(GLfloat), 16 );
208 mat->inv = m = mat->m;
209
210 init_matrix( m );
211
212 scale = 1.0F + rnd () * norm_scale_types[mtype];
213
214 for ( i = 0 ; i < 4 ; i++ ) {
215 for ( j = 0 ; j < 4 ; j++ ) {
216 switch ( norm_templates[mtype][i * 4 + j] ) {
217 case NIL:
218 m[j * 4 + i] = 0.0;
219 break;
220 case ONE:
221 m[j * 4 + i] = 1.0;
222 break;
223 case NEG:
224 m[j * 4 + i] = -1.0;
225 break;
226 case VAR:
227 break;
228 default:
229 abort();
230 }
231 }
232 }
233
234 for ( i = 0 ; i < TEST_COUNT ; i++ ) {
235 ASSIGN_3V( d[i], 0.0, 0.0, 0.0 );
236 ASSIGN_3V( s[i], 0.0, 0.0, 0.0 );
237 ASSIGN_3V( d2[i], 0.0, 0.0, 0.0 );
238 for ( j = 0 ; j < 3 ; j++ )
239 s[i][j] = rnd();
240 length[i] = 1 / sqrt( LEN_SQUARED_3FV( s[i] ) );
241 }
242
243 source->data = (GLfloat(*)[4]) s;
244 source->start = (GLfloat *) s;
245 source->count = TEST_COUNT;
246 source->stride = sizeof(s[0]);
247 source->flags = 0;
248
249 dest->data = d;
250 dest->start = (GLfloat *) d;
251 dest->count = TEST_COUNT;
252 dest->stride = sizeof(float[4]);
253 dest->flags = 0;
254
255 dest2->data = d2;
256 dest2->start = (GLfloat *) d2;
257 dest2->count = TEST_COUNT;
258 dest2->stride = sizeof(float[4]);
259 dest2->flags = 0;
260
261 ref->data = r;
262 ref->start = (GLfloat *) r;
263 ref->count = TEST_COUNT;
264 ref->stride = sizeof(float[4]);
265 ref->flags = 0;
266
267 ref2->data = r2;
268 ref2->start = (GLfloat *) r2;
269 ref2->count = TEST_COUNT;
270 ref2->stride = sizeof(float[4]);
271 ref2->flags = 0;
272
273 if ( norm_normalize_types[mtype] == 0 ) {
274 ref_norm_transform_rescale( mat, scale, source, NULL, ref );
275 } else {
276 ref_norm_transform_normalize( mat, scale, source, NULL, ref );
277 ref_norm_transform_normalize( mat, scale, source, length, ref2 );
278 }
279
280 if ( mesa_profile ) {
281 BEGIN_RACE( *cycles );
282 func( mat, scale, source, NULL, dest );
283 END_RACE( *cycles );
284 func( mat, scale, source, length, dest2 );
285 } else {
286 func( mat, scale, source, NULL, dest );
287 func( mat, scale, source, length, dest2 );
288 }
289
290 for ( i = 0 ; i < TEST_COUNT ; i++ ) {
291 for ( j = 0 ; j < 3 ; j++ ) {
292 if ( significand_match( d[i][j], r[i][j] ) < REQUIRED_PRECISION ) {
293 _mesa_printf( "-----------------------------\n" );
294 _mesa_printf( "(i = %i, j = %i)\n", i, j );
295 _mesa_printf( "%f \t %f \t [ratio = %e - %i bit missed]\n",
296 d[i][0], r[i][0], r[i][0]/d[i][0],
297 MAX_PRECISION - significand_match( d[i][0], r[i][0] ) );
298 _mesa_printf( "%f \t %f \t [ratio = %e - %i bit missed]\n",
299 d[i][1], r[i][1], r[i][1]/d[i][1],
300 MAX_PRECISION - significand_match( d[i][1], r[i][1] ) );
301 _mesa_printf( "%f \t %f \t [ratio = %e - %i bit missed]\n",
302 d[i][2], r[i][2], r[i][2]/d[i][2],
303 MAX_PRECISION - significand_match( d[i][2], r[i][2] ) );
304 return 0;
305 }
306
307 if ( norm_normalize_types[mtype] != 0 ) {
308 if ( significand_match( d2[i][j], r2[i][j] ) < REQUIRED_PRECISION ) {
309 _mesa_printf( "------------------- precalculated length case ------\n" );
310 _mesa_printf( "(i = %i, j = %i)\n", i, j );
311 _mesa_printf( "%f \t %f \t [ratio = %e - %i bit missed]\n",
312 d2[i][0], r2[i][0], r2[i][0]/d2[i][0],
313 MAX_PRECISION - significand_match( d2[i][0], r2[i][0] ) );
314 _mesa_printf( "%f \t %f \t [ratio = %e - %i bit missed]\n",
315 d2[i][1], r2[i][1], r2[i][1]/d2[i][1],
316 MAX_PRECISION - significand_match( d2[i][1], r2[i][1] ) );
317 _mesa_printf( "%f \t %f \t [ratio = %e - %i bit missed]\n",
318 d2[i][2], r2[i][2], r2[i][2]/d2[i][2],
319 MAX_PRECISION - significand_match( d2[i][2], r2[i][2] ) );
320 return 0;
321 }
322 }
323 }
324 }
325
326 ALIGN_FREE( mat->m );
327 return 1;
328 }
329
330 void _math_test_all_normal_transform_functions( char *description )
331 {
332 int mtype;
333 long benchmark_tab[0xf];
334 static int first_time = 1;
335
336 if ( first_time ) {
337 first_time = 0;
338 mesa_profile = getenv( "MESA_PROFILE" );
339 }
340
341 #ifdef RUN_DEBUG_BENCHMARK
342 if ( mesa_profile ) {
343 if ( !counter_overhead ) {
344 INIT_COUNTER();
345 _mesa_printf( "counter overhead: %ld cycles\n\n", counter_overhead );
346 }
347 _mesa_printf( "normal transform results after hooking in %s functions:\n",
348 description );
349 _mesa_printf( "\n-------------------------------------------------------\n" );
350 }
351 #endif
352
353 for ( mtype = 0 ; mtype < 8 ; mtype++ ) {
354 normal_func func = _mesa_normal_tab[norm_types[mtype]];
355 long *cycles = &benchmark_tab[mtype];
356
357 if ( test_norm_function( func, mtype, cycles ) == 0 ) {
358 char buf[100];
359 _mesa_sprintf( buf, "_mesa_normal_tab[0][%s] failed test (%s)",
360 norm_strings[mtype], description );
361 _mesa_problem( NULL, buf );
362 }
363
364 #ifdef RUN_DEBUG_BENCHMARK
365 if ( mesa_profile ) {
366 _mesa_printf( " %li\t", benchmark_tab[mtype] );
367 _mesa_printf( " | [%s]\n", norm_strings[mtype] );
368 }
369 #endif
370 }
371 #ifdef RUN_DEBUG_BENCHMARK
372 if ( mesa_profile ) {
373 _mesa_printf( "\n" );
374 fflush( stdout );
375 }
376 #endif
377 }
378
379
380 #endif /* DEBUG */