static void ref_norm_transform_normalize( const GLmatrix *mat, GLfloat scale, const GLvector4f *in, const GLfloat *lengths, GLvector4f *dest ) { GLuint i; const GLfloat *s = in->start; const GLfloat *m = mat->inv; GLfloat (*out)[4] = (GLfloat (*)[4]) dest->start; for ( i = 0 ; i < in->count ; i++ ) { GLfloat t[3]; TRANSFORM_NORMAL( t, s, m ); if ( !lengths ) { GLfloat len = LEN_SQUARED_3FV( t ); if ( len > 1e-20 ) { /* Hmmm, don't know how we could test the precalculated * length case... */ scale = 1.0 / SQRTF( len ); SCALE_SCALAR_3V( out[i], scale, t ); } else { out[i][0] = out[i][1] = out[i][2] = 0; } } else { scale = lengths[i];; SCALE_SCALAR_3V( out[i], scale, t ); } s = (GLfloat *)((char *)s + in->stride); } }
static int test_norm_function( normal_func func, int mtype, long *cycles ) { GLvector4f source[1], dest[1], dest2[1], ref[1], ref2[1]; GLmatrix mat[1]; GLfloat s[TEST_COUNT][5], d[TEST_COUNT][4], r[TEST_COUNT][4]; GLfloat d2[TEST_COUNT][4], r2[TEST_COUNT][4], length[TEST_COUNT]; GLfloat scale; GLfloat *m; int i, j; #ifdef RUN_DEBUG_BENCHMARK int cycle_i; /* the counter for the benchmarks we run */ #endif (void) cycles; mat->m = (GLfloat *) _mesa_align_malloc( 16 * sizeof(GLfloat), 16 ); mat->inv = m = mat->m; init_matrix( m ); scale = 1.0F + rnd () * norm_scale_types[mtype]; for ( i = 0 ; i < 4 ; i++ ) { for ( j = 0 ; j < 4 ; j++ ) { switch ( norm_templates[mtype][i * 4 + j] ) { case NIL: m[j * 4 + i] = 0.0; break; case ONE: m[j * 4 + i] = 1.0; break; case NEG: m[j * 4 + i] = -1.0; break; case VAR: break; default: exit(1); } } } for ( i = 0 ; i < TEST_COUNT ; i++ ) { ASSIGN_3V( d[i], 0.0, 0.0, 0.0 ); ASSIGN_3V( s[i], 0.0, 0.0, 0.0 ); ASSIGN_3V( d2[i], 0.0, 0.0, 0.0 ); for ( j = 0 ; j < 3 ; j++ ) s[i][j] = rnd(); length[i] = 1 / SQRTF( LEN_SQUARED_3FV( s[i] ) ); } source->data = (GLfloat(*)[4]) s; source->start = (GLfloat *) s; source->count = TEST_COUNT; source->stride = sizeof(s[0]); source->flags = 0; dest->data = d; dest->start = (GLfloat *) d; dest->count = TEST_COUNT; dest->stride = sizeof(float[4]); dest->flags = 0; dest2->data = d2; dest2->start = (GLfloat *) d2; dest2->count = TEST_COUNT; dest2->stride = sizeof(float[4]); dest2->flags = 0; ref->data = r; ref->start = (GLfloat *) r; ref->count = TEST_COUNT; ref->stride = sizeof(float[4]); ref->flags = 0; ref2->data = r2; ref2->start = (GLfloat *) r2; ref2->count = TEST_COUNT; ref2->stride = sizeof(float[4]); ref2->flags = 0; if ( norm_normalize_types[mtype] == 0 ) { ref_norm_transform_rescale( mat, scale, source, NULL, ref ); } else { ref_norm_transform_normalize( mat, scale, source, NULL, ref ); ref_norm_transform_normalize( mat, scale, source, length, ref2 ); } if ( mesa_profile ) { BEGIN_RACE( *cycles ); func( mat, scale, source, NULL, dest ); END_RACE( *cycles ); func( mat, scale, source, length, dest2 ); } else { func( mat, scale, source, NULL, dest ); func( mat, scale, source, length, dest2 ); } for ( i = 0 ; i < TEST_COUNT ; i++ ) { for ( j = 0 ; j < 3 ; j++ ) { if ( significand_match( d[i][j], r[i][j] ) < REQUIRED_PRECISION ) { printf( "-----------------------------\n" ); printf( "(i = %i, j = %i)\n", i, j ); printf( "%f \t %f \t [ratio = %e - %i bit missed]\n", d[i][0], r[i][0], r[i][0]/d[i][0], MAX_PRECISION - significand_match( d[i][0], r[i][0] ) ); printf( "%f \t %f \t [ratio = %e - %i bit missed]\n", d[i][1], r[i][1], r[i][1]/d[i][1], MAX_PRECISION - significand_match( d[i][1], r[i][1] ) ); printf( "%f \t %f \t [ratio = %e - %i bit missed]\n", d[i][2], r[i][2], r[i][2]/d[i][2], MAX_PRECISION - significand_match( d[i][2], r[i][2] ) ); return 0; } if ( norm_normalize_types[mtype] != 0 ) { if ( significand_match( d2[i][j], r2[i][j] ) < REQUIRED_PRECISION ) { printf( "------------------- precalculated length case ------\n" ); printf( "(i = %i, j = %i)\n", i, j ); printf( "%f \t %f \t [ratio = %e - %i bit missed]\n", d2[i][0], r2[i][0], r2[i][0]/d2[i][0], MAX_PRECISION - significand_match( d2[i][0], r2[i][0] ) ); printf( "%f \t %f \t [ratio = %e - %i bit missed]\n", d2[i][1], r2[i][1], r2[i][1]/d2[i][1], MAX_PRECISION - significand_match( d2[i][1], r2[i][1] ) ); printf( "%f \t %f \t [ratio = %e - %i bit missed]\n", d2[i][2], r2[i][2], r2[i][2]/d2[i][2], MAX_PRECISION - significand_match( d2[i][2], r2[i][2] ) ); return 0; } } } } _mesa_align_free( mat->m ); return 1; }
/** * Determine type and flags from scratch. * * \param mat matrix. * * This is expensive enough to only want to do it once. */ static void analyse_from_scratch( GLmatrix *mat ) { const GLfloat *m = mat->m; GLuint mask = 0; GLuint i; for (i = 0 ; i < 16 ; i++) { if (m[i] == 0.0) mask |= (1<<i); } if (m[0] == 1.0F) mask |= (1<<16); if (m[5] == 1.0F) mask |= (1<<21); if (m[10] == 1.0F) mask |= (1<<26); if (m[15] == 1.0F) mask |= (1<<31); mat->flags &= ~MAT_FLAGS_GEOMETRY; /* Check for translation - no-one really cares */ if ((mask & MASK_NO_TRX) != MASK_NO_TRX) mat->flags |= MAT_FLAG_TRANSLATION; /* Do the real work */ if (mask == (GLuint) MASK_IDENTITY) { mat->type = MATRIX_IDENTITY; } else if ((mask & MASK_2D_NO_ROT) == (GLuint) MASK_2D_NO_ROT) { mat->type = MATRIX_2D_NO_ROT; if ((mask & MASK_NO_2D_SCALE) != MASK_NO_2D_SCALE) mat->flags |= MAT_FLAG_GENERAL_SCALE; } else if ((mask & MASK_2D) == (GLuint) MASK_2D) { GLfloat mm = DOT2(m, m); GLfloat m4m4 = DOT2(m+4,m+4); GLfloat mm4 = DOT2(m,m+4); mat->type = MATRIX_2D; /* Check for scale */ if (SQ(mm-1) > SQ(1e-6) || SQ(m4m4-1) > SQ(1e-6)) mat->flags |= MAT_FLAG_GENERAL_SCALE; /* Check for rotation */ if (SQ(mm4) > SQ(1e-6)) mat->flags |= MAT_FLAG_GENERAL_3D; else mat->flags |= MAT_FLAG_ROTATION; } else if ((mask & MASK_3D_NO_ROT) == (GLuint) MASK_3D_NO_ROT) { mat->type = MATRIX_3D_NO_ROT; /* Check for scale */ if (SQ(m[0]-m[5]) < SQ(1e-6) && SQ(m[0]-m[10]) < SQ(1e-6)) { if (SQ(m[0]-1.0) > SQ(1e-6)) { mat->flags |= MAT_FLAG_UNIFORM_SCALE; } } else { mat->flags |= MAT_FLAG_GENERAL_SCALE; } } else if ((mask & MASK_3D) == (GLuint) MASK_3D) { GLfloat c1 = DOT3(m,m); GLfloat c2 = DOT3(m+4,m+4); GLfloat c3 = DOT3(m+8,m+8); GLfloat d1 = DOT3(m, m+4); GLfloat cp[3]; mat->type = MATRIX_3D; /* Check for scale */ if (SQ(c1-c2) < SQ(1e-6) && SQ(c1-c3) < SQ(1e-6)) { if (SQ(c1-1.0) > SQ(1e-6)) mat->flags |= MAT_FLAG_UNIFORM_SCALE; /* else no scale at all */ } else { mat->flags |= MAT_FLAG_GENERAL_SCALE; } /* Check for rotation */ if (SQ(d1) < SQ(1e-6)) { CROSS3( cp, m, m+4 ); SUB_3V( cp, cp, (m+8) ); if (LEN_SQUARED_3FV(cp) < SQ(1e-6)) mat->flags |= MAT_FLAG_ROTATION; else mat->flags |= MAT_FLAG_GENERAL_3D; } else { mat->flags |= MAT_FLAG_GENERAL_3D; /* shear, etc */ } } else if ((mask & MASK_PERSPECTIVE) == MASK_PERSPECTIVE && m[11]==-1.0F) { mat->type = MATRIX_PERSPECTIVE; mat->flags |= MAT_FLAG_GENERAL; } else { mat->type = MATRIX_GENERAL; mat->flags |= MAT_FLAG_GENERAL; } }