17117f1b4Smrg/* 27117f1b4Smrg * Mesa 3-D graphics library 37117f1b4Smrg * 47117f1b4Smrg * Copyright (C) 1999-2005 Brian Paul All Rights Reserved. 57117f1b4Smrg * 67117f1b4Smrg * Permission is hereby granted, free of charge, to any person obtaining a 77117f1b4Smrg * copy of this software and associated documentation files (the "Software"), 87117f1b4Smrg * to deal in the Software without restriction, including without limitation 97117f1b4Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 107117f1b4Smrg * and/or sell copies of the Software, and to permit persons to whom the 117117f1b4Smrg * Software is furnished to do so, subject to the following conditions: 127117f1b4Smrg * 137117f1b4Smrg * The above copyright notice and this permission notice shall be included 147117f1b4Smrg * in all copies or substantial portions of the Software. 157117f1b4Smrg * 167117f1b4Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 177117f1b4Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 187117f1b4Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19af69d88dSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20af69d88dSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21af69d88dSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22af69d88dSmrg * OTHER DEALINGS IN THE SOFTWARE. 237117f1b4Smrg * 247117f1b4Smrg * Authors: 257117f1b4Smrg * Gareth Hughes 267117f1b4Smrg */ 277117f1b4Smrg 28c1f859d4Smrg#include "main/glheader.h" 29c1f859d4Smrg#include "main/context.h" 30c1f859d4Smrg#include "main/macros.h" 317ec681f3Smrg 327117f1b4Smrg 337117f1b4Smrg#include "m_matrix.h" 347117f1b4Smrg#include "m_xform.h" 357117f1b4Smrg 367117f1b4Smrg#include "m_debug.h" 377117f1b4Smrg#include "m_debug_util.h" 387117f1b4Smrg 397117f1b4Smrg#ifdef __UNIXOS2__ 407117f1b4Smrg/* The linker doesn't like empty files */ 417117f1b4Smrgstatic char dummy; 427117f1b4Smrg#endif 437117f1b4Smrg 447117f1b4Smrg#ifdef DEBUG_MATH /* This code only used for debugging */ 457117f1b4Smrg 467117f1b4Smrgstatic clip_func *clip_tab[2] = { 477117f1b4Smrg _mesa_clip_tab, 487117f1b4Smrg _mesa_clip_np_tab 497117f1b4Smrg}; 507117f1b4Smrgstatic char *cnames[2] = { 517117f1b4Smrg "_mesa_clip_tab", 527117f1b4Smrg "_mesa_clip_np_tab" 537117f1b4Smrg}; 547117f1b4Smrg#ifdef RUN_DEBUG_BENCHMARK 557117f1b4Smrgstatic char *cstrings[2] = { 567117f1b4Smrg "clip, perspective divide", 577117f1b4Smrg "clip, no divide" 587117f1b4Smrg}; 597117f1b4Smrg#endif 607117f1b4Smrg 617117f1b4Smrg 627117f1b4Smrg/* ============================================================= 637117f1b4Smrg * Reference cliptests 647117f1b4Smrg */ 657117f1b4Smrg 667117f1b4Smrgstatic GLvector4f *ref_cliptest_points4( GLvector4f *clip_vec, 677117f1b4Smrg GLvector4f *proj_vec, 687117f1b4Smrg GLubyte clipMask[], 697117f1b4Smrg GLubyte *orMask, 704a49301eSmrg GLubyte *andMask, 714a49301eSmrg GLboolean viewport_z_clip ) 727117f1b4Smrg{ 737117f1b4Smrg const GLuint stride = clip_vec->stride; 747117f1b4Smrg const GLuint count = clip_vec->count; 757117f1b4Smrg const GLfloat *from = (GLfloat *)clip_vec->start; 767117f1b4Smrg GLuint c = 0; 777117f1b4Smrg GLfloat (*vProj)[4] = (GLfloat (*)[4])proj_vec->start; 787117f1b4Smrg GLubyte tmpAndMask = *andMask; 797117f1b4Smrg GLubyte tmpOrMask = *orMask; 807117f1b4Smrg GLuint i; 817117f1b4Smrg for ( i = 0 ; i < count ; i++, STRIDE_F(from, stride) ) { 827117f1b4Smrg const GLfloat cx = from[0]; 837117f1b4Smrg const GLfloat cy = from[1]; 847117f1b4Smrg const GLfloat cz = from[2]; 857117f1b4Smrg const GLfloat cw = from[3]; 867117f1b4Smrg GLubyte mask = 0; 877117f1b4Smrg if ( -cx + cw < 0 ) mask |= CLIP_RIGHT_BIT; 887117f1b4Smrg if ( cx + cw < 0 ) mask |= CLIP_LEFT_BIT; 897117f1b4Smrg if ( -cy + cw < 0 ) mask |= CLIP_TOP_BIT; 907117f1b4Smrg if ( cy + cw < 0 ) mask |= CLIP_BOTTOM_BIT; 914a49301eSmrg if (viewport_z_clip) { 924a49301eSmrg if ( -cz + cw < 0 ) mask |= CLIP_FAR_BIT; 934a49301eSmrg if ( cz + cw < 0 ) mask |= CLIP_NEAR_BIT; 944a49301eSmrg } 957117f1b4Smrg clipMask[i] = mask; 967117f1b4Smrg if ( mask ) { 977117f1b4Smrg c++; 987117f1b4Smrg tmpAndMask &= mask; 997117f1b4Smrg tmpOrMask |= mask; 1007117f1b4Smrg vProj[i][0] = 0; 1017117f1b4Smrg vProj[i][1] = 0; 1027117f1b4Smrg vProj[i][2] = 0; 1037117f1b4Smrg vProj[i][3] = 1; 1047117f1b4Smrg } else { 1057117f1b4Smrg GLfloat oow = 1.0F / cw; 1067117f1b4Smrg vProj[i][0] = cx * oow; 1077117f1b4Smrg vProj[i][1] = cy * oow; 1087117f1b4Smrg vProj[i][2] = cz * oow; 1097117f1b4Smrg vProj[i][3] = oow; 1107117f1b4Smrg } 1117117f1b4Smrg } 1127117f1b4Smrg 1137117f1b4Smrg *orMask = tmpOrMask; 1147117f1b4Smrg *andMask = (GLubyte) (c < count ? 0 : tmpAndMask); 1157117f1b4Smrg 1167117f1b4Smrg proj_vec->flags |= VEC_SIZE_4; 1177117f1b4Smrg proj_vec->size = 4; 1187117f1b4Smrg proj_vec->count = clip_vec->count; 1197117f1b4Smrg return proj_vec; 1207117f1b4Smrg} 1217117f1b4Smrg 1227117f1b4Smrg/* Keep these here for now, even though we don't use them... 1237117f1b4Smrg */ 1247117f1b4Smrgstatic GLvector4f *ref_cliptest_points3( GLvector4f *clip_vec, 1257117f1b4Smrg GLvector4f *proj_vec, 1267117f1b4Smrg GLubyte clipMask[], 1277117f1b4Smrg GLubyte *orMask, 1284a49301eSmrg GLubyte *andMask, 1294a49301eSmrg GLboolean viewport_z_clip ) 1307117f1b4Smrg{ 1317117f1b4Smrg const GLuint stride = clip_vec->stride; 1327117f1b4Smrg const GLuint count = clip_vec->count; 1337117f1b4Smrg const GLfloat *from = (GLfloat *)clip_vec->start; 1347117f1b4Smrg 1357117f1b4Smrg GLubyte tmpOrMask = *orMask; 1367117f1b4Smrg GLubyte tmpAndMask = *andMask; 1377117f1b4Smrg GLuint i; 1387117f1b4Smrg for ( i = 0 ; i < count ; i++, STRIDE_F(from, stride) ) { 1397117f1b4Smrg const GLfloat cx = from[0], cy = from[1], cz = from[2]; 1407117f1b4Smrg GLubyte mask = 0; 1417117f1b4Smrg if ( cx > 1.0 ) mask |= CLIP_RIGHT_BIT; 1427117f1b4Smrg else if ( cx < -1.0 ) mask |= CLIP_LEFT_BIT; 1437117f1b4Smrg if ( cy > 1.0 ) mask |= CLIP_TOP_BIT; 1447117f1b4Smrg else if ( cy < -1.0 ) mask |= CLIP_BOTTOM_BIT; 1454a49301eSmrg if (viewport_z_clip) { 1464a49301eSmrg if ( cz > 1.0 ) mask |= CLIP_FAR_BIT; 1474a49301eSmrg else if ( cz < -1.0 ) mask |= CLIP_NEAR_BIT; 1484a49301eSmrg } 1497117f1b4Smrg clipMask[i] = mask; 1507117f1b4Smrg tmpOrMask |= mask; 1517117f1b4Smrg tmpAndMask &= mask; 1527117f1b4Smrg } 1537117f1b4Smrg 1547117f1b4Smrg *orMask = tmpOrMask; 1557117f1b4Smrg *andMask = tmpAndMask; 1567117f1b4Smrg return clip_vec; 1577117f1b4Smrg} 1587117f1b4Smrg 1597117f1b4Smrgstatic GLvector4f * ref_cliptest_points2( GLvector4f *clip_vec, 1607117f1b4Smrg GLvector4f *proj_vec, 1617117f1b4Smrg GLubyte clipMask[], 1627117f1b4Smrg GLubyte *orMask, 1634a49301eSmrg GLubyte *andMask, 1644a49301eSmrg GLboolean viewport_z_clip ) 1657117f1b4Smrg{ 1667117f1b4Smrg const GLuint stride = clip_vec->stride; 1677117f1b4Smrg const GLuint count = clip_vec->count; 1687117f1b4Smrg const GLfloat *from = (GLfloat *)clip_vec->start; 1697117f1b4Smrg 1707117f1b4Smrg GLubyte tmpOrMask = *orMask; 1717117f1b4Smrg GLubyte tmpAndMask = *andMask; 1727117f1b4Smrg GLuint i; 1734a49301eSmrg 1744a49301eSmrg (void) viewport_z_clip; 1754a49301eSmrg 1767117f1b4Smrg for ( i = 0 ; i < count ; i++, STRIDE_F(from, stride) ) { 1777117f1b4Smrg const GLfloat cx = from[0], cy = from[1]; 1787117f1b4Smrg GLubyte mask = 0; 1797117f1b4Smrg if ( cx > 1.0 ) mask |= CLIP_RIGHT_BIT; 1807117f1b4Smrg else if ( cx < -1.0 ) mask |= CLIP_LEFT_BIT; 1817117f1b4Smrg if ( cy > 1.0 ) mask |= CLIP_TOP_BIT; 1827117f1b4Smrg else if ( cy < -1.0 ) mask |= CLIP_BOTTOM_BIT; 1837117f1b4Smrg clipMask[i] = mask; 1847117f1b4Smrg tmpOrMask |= mask; 1857117f1b4Smrg tmpAndMask &= mask; 1867117f1b4Smrg } 1877117f1b4Smrg 1887117f1b4Smrg *orMask = tmpOrMask; 1897117f1b4Smrg *andMask = tmpAndMask; 1907117f1b4Smrg return clip_vec; 1917117f1b4Smrg} 1927117f1b4Smrg 1937117f1b4Smrgstatic clip_func ref_cliptest[5] = { 1947117f1b4Smrg 0, 1957117f1b4Smrg 0, 1967117f1b4Smrg ref_cliptest_points2, 1977117f1b4Smrg ref_cliptest_points3, 1987117f1b4Smrg ref_cliptest_points4 1997117f1b4Smrg}; 2007117f1b4Smrg 2017117f1b4Smrg 2027117f1b4Smrg/* ============================================================= 2037117f1b4Smrg * Cliptest tests 2047117f1b4Smrg */ 2057117f1b4Smrg 2067ec681f3SmrgALIGN16 static GLfloat s[TEST_COUNT][4]; 2077ec681f3SmrgALIGN16 static GLfloat d[TEST_COUNT][4]; 2087ec681f3SmrgALIGN16 static GLfloat r[TEST_COUNT][4]; 2097117f1b4Smrg 2107117f1b4Smrg 2113464ebd5Sriastradh/** 2123464ebd5Sriastradh * Check if X, Y or Z component of the coordinate is close to W, in terms 2133464ebd5Sriastradh * of the clip test. 2143464ebd5Sriastradh */ 2153464ebd5Sriastradhstatic GLboolean 2163464ebd5Sriastradhxyz_close_to_w(const GLfloat c[4]) 2173464ebd5Sriastradh{ 2183464ebd5Sriastradh float k = 0.0001; 2193464ebd5Sriastradh return (fabs(c[0] - c[3]) < k || 2203464ebd5Sriastradh fabs(c[1] - c[3]) < k || 2213464ebd5Sriastradh fabs(c[2] - c[3]) < k || 2223464ebd5Sriastradh fabs(-c[0] - c[3]) < k || 2233464ebd5Sriastradh fabs(-c[1] - c[3]) < k || 2243464ebd5Sriastradh fabs(-c[2] - c[3]) < k); 2253464ebd5Sriastradh} 2263464ebd5Sriastradh 2273464ebd5Sriastradh 2283464ebd5Sriastradh 2297117f1b4Smrgstatic int test_cliptest_function( clip_func func, int np, 2307117f1b4Smrg int psize, long *cycles ) 2317117f1b4Smrg{ 2327117f1b4Smrg GLvector4f source[1], dest[1], ref[1]; 2337117f1b4Smrg GLubyte dm[TEST_COUNT], dco, dca; 2347117f1b4Smrg GLubyte rm[TEST_COUNT], rco, rca; 2357117f1b4Smrg int i, j; 2367117f1b4Smrg#ifdef RUN_DEBUG_BENCHMARK 2377117f1b4Smrg int cycle_i; /* the counter for the benchmarks we run */ 2387117f1b4Smrg#endif 2394a49301eSmrg GLboolean viewport_z_clip = GL_TRUE; 2407117f1b4Smrg 2417117f1b4Smrg (void) cycles; 2427117f1b4Smrg 2437117f1b4Smrg if ( psize > 4 ) { 2447117f1b4Smrg _mesa_problem( NULL, "test_cliptest_function called with psize > 4\n" ); 2457117f1b4Smrg return 0; 2467117f1b4Smrg } 2477117f1b4Smrg 2487117f1b4Smrg for ( i = 0 ; i < TEST_COUNT ; i++) { 2497117f1b4Smrg ASSIGN_4V( d[i], 0.0, 0.0, 0.0, 1.0 ); 2507117f1b4Smrg ASSIGN_4V( s[i], 0.0, 0.0, 0.0, 1.0 ); 2517117f1b4Smrg for ( j = 0 ; j < psize ; j++ ) 2527117f1b4Smrg s[i][j] = rnd(); 2537117f1b4Smrg } 2547117f1b4Smrg 2557117f1b4Smrg source->data = (GLfloat(*)[4])s; 2567117f1b4Smrg source->start = (GLfloat *)s; 2577117f1b4Smrg source->count = TEST_COUNT; 2587117f1b4Smrg source->stride = sizeof(s[0]); 2597117f1b4Smrg source->size = 4; 2607117f1b4Smrg source->flags = 0; 2617117f1b4Smrg 2627117f1b4Smrg dest->data = (GLfloat(*)[4])d; 2637117f1b4Smrg dest->start = (GLfloat *)d; 2647117f1b4Smrg dest->count = TEST_COUNT; 2657117f1b4Smrg dest->stride = sizeof(float[4]); 2667117f1b4Smrg dest->size = 0; 2677117f1b4Smrg dest->flags = 0; 2687117f1b4Smrg 2697117f1b4Smrg ref->data = (GLfloat(*)[4])r; 2707117f1b4Smrg ref->start = (GLfloat *)r; 2717117f1b4Smrg ref->count = TEST_COUNT; 2727117f1b4Smrg ref->stride = sizeof(float[4]); 2737117f1b4Smrg ref->size = 0; 2747117f1b4Smrg ref->flags = 0; 2757117f1b4Smrg 2767117f1b4Smrg dco = rco = 0; 2777117f1b4Smrg dca = rca = CLIP_FRUSTUM_BITS; 2787117f1b4Smrg 2794a49301eSmrg ref_cliptest[psize]( source, ref, rm, &rco, &rca, viewport_z_clip ); 2807117f1b4Smrg 2817117f1b4Smrg if ( mesa_profile ) { 2827117f1b4Smrg BEGIN_RACE( *cycles ); 2834a49301eSmrg func( source, dest, dm, &dco, &dca, viewport_z_clip ); 2847117f1b4Smrg END_RACE( *cycles ); 2857117f1b4Smrg } 2867117f1b4Smrg else { 2874a49301eSmrg func( source, dest, dm, &dco, &dca, viewport_z_clip ); 2887117f1b4Smrg } 2897117f1b4Smrg 2907117f1b4Smrg if ( dco != rco ) { 291cdc920a0Smrg printf( "\n-----------------------------\n" ); 292cdc920a0Smrg printf( "dco = 0x%02x rco = 0x%02x\n", dco, rco ); 2937117f1b4Smrg return 0; 2947117f1b4Smrg } 2957117f1b4Smrg if ( dca != rca ) { 296cdc920a0Smrg printf( "\n-----------------------------\n" ); 297cdc920a0Smrg printf( "dca = 0x%02x rca = 0x%02x\n", dca, rca ); 2987117f1b4Smrg return 0; 2997117f1b4Smrg } 3007117f1b4Smrg for ( i = 0 ; i < TEST_COUNT ; i++ ) { 3017117f1b4Smrg if ( dm[i] != rm[i] ) { 3023464ebd5Sriastradh GLfloat *c = source->start; 3033464ebd5Sriastradh STRIDE_F(c, source->stride * i); 3043464ebd5Sriastradh if (psize == 4 && xyz_close_to_w(c)) { 3053464ebd5Sriastradh /* The coordinate is very close to the clip plane. The clipmask 3063464ebd5Sriastradh * may vary depending on code path, but that's OK. 3073464ebd5Sriastradh */ 3083464ebd5Sriastradh continue; 3093464ebd5Sriastradh } 310cdc920a0Smrg printf( "\n-----------------------------\n" ); 3113464ebd5Sriastradh printf( "mask[%d] = 0x%02x ref mask[%d] = 0x%02x\n", i, dm[i], i,rm[i] ); 3123464ebd5Sriastradh printf(" coord = %f, %f, %f, %f\n", 3133464ebd5Sriastradh c[0], c[1], c[2], c[3]); 3147117f1b4Smrg return 0; 3157117f1b4Smrg } 3167117f1b4Smrg } 3177117f1b4Smrg 3187117f1b4Smrg /* Only verify output on projected points4 case. FIXME: Do we need 3197117f1b4Smrg * to test other cases? 3207117f1b4Smrg */ 3217117f1b4Smrg if ( np || psize < 4 ) 3227117f1b4Smrg return 1; 3237117f1b4Smrg 3247117f1b4Smrg for ( i = 0 ; i < TEST_COUNT ; i++ ) { 3257117f1b4Smrg for ( j = 0 ; j < 4 ; j++ ) { 3267117f1b4Smrg if ( significand_match( d[i][j], r[i][j] ) < REQUIRED_PRECISION ) { 327cdc920a0Smrg printf( "\n-----------------------------\n" ); 328cdc920a0Smrg printf( "(i = %i, j = %i) dm = 0x%02x rm = 0x%02x\n", 3297117f1b4Smrg i, j, dm[i], rm[i] ); 330cdc920a0Smrg printf( "%f \t %f \t [diff = %e - %i bit missed]\n", 3317117f1b4Smrg d[i][0], r[i][0], r[i][0]-d[i][0], 3327117f1b4Smrg MAX_PRECISION - significand_match( d[i][0], r[i][0] ) ); 333cdc920a0Smrg printf( "%f \t %f \t [diff = %e - %i bit missed]\n", 3347117f1b4Smrg d[i][1], r[i][1], r[i][1]-d[i][1], 3357117f1b4Smrg MAX_PRECISION - significand_match( d[i][1], r[i][1] ) ); 336cdc920a0Smrg printf( "%f \t %f \t [diff = %e - %i bit missed]\n", 3377117f1b4Smrg d[i][2], r[i][2], r[i][2]-d[i][2], 3387117f1b4Smrg MAX_PRECISION - significand_match( d[i][2], r[i][2] ) ); 339cdc920a0Smrg printf( "%f \t %f \t [diff = %e - %i bit missed]\n", 3407117f1b4Smrg d[i][3], r[i][3], r[i][3]-d[i][3], 3417117f1b4Smrg MAX_PRECISION - significand_match( d[i][3], r[i][3] ) ); 3427117f1b4Smrg return 0; 3437117f1b4Smrg } 3447117f1b4Smrg } 3457117f1b4Smrg } 3467117f1b4Smrg 3477117f1b4Smrg return 1; 3487117f1b4Smrg} 3497117f1b4Smrg 3507117f1b4Smrgvoid _math_test_all_cliptest_functions( char *description ) 3517117f1b4Smrg{ 3527117f1b4Smrg int np, psize; 3537117f1b4Smrg long benchmark_tab[2][4]; 3547117f1b4Smrg static int first_time = 1; 3557117f1b4Smrg 3567117f1b4Smrg if ( first_time ) { 3577117f1b4Smrg first_time = 0; 35801e04c3fSmrg mesa_profile = getenv( "MESA_PROFILE" ); 3597117f1b4Smrg } 3607117f1b4Smrg 3617117f1b4Smrg#ifdef RUN_DEBUG_BENCHMARK 3627117f1b4Smrg if ( mesa_profile ) { 3637117f1b4Smrg if ( !counter_overhead ) { 3647117f1b4Smrg INIT_COUNTER(); 365cdc920a0Smrg printf( "counter overhead: %ld cycles\n\n", counter_overhead ); 3667117f1b4Smrg } 367cdc920a0Smrg printf( "cliptest results after hooking in %s functions:\n", description ); 3687117f1b4Smrg } 3697117f1b4Smrg#endif 3707117f1b4Smrg 3717117f1b4Smrg#ifdef RUN_DEBUG_BENCHMARK 3727117f1b4Smrg if ( mesa_profile ) { 373cdc920a0Smrg printf( "\n\t" ); 3747117f1b4Smrg for ( psize = 2 ; psize <= 4 ; psize++ ) { 375cdc920a0Smrg printf( " p%d\t", psize ); 3767117f1b4Smrg } 377cdc920a0Smrg printf( "\n--------------------------------------------------------\n\t" ); 3787117f1b4Smrg } 3797117f1b4Smrg#endif 3807117f1b4Smrg 3817117f1b4Smrg for ( np = 0 ; np < 2 ; np++ ) { 3827117f1b4Smrg for ( psize = 2 ; psize <= 4 ; psize++ ) { 3837117f1b4Smrg clip_func func = clip_tab[np][psize]; 3847117f1b4Smrg long *cycles = &(benchmark_tab[np][psize-1]); 3857117f1b4Smrg 3867117f1b4Smrg if ( test_cliptest_function( func, np, psize, cycles ) == 0 ) { 3877117f1b4Smrg char buf[100]; 388cdc920a0Smrg sprintf( buf, "%s[%d] failed test (%s)", 3897117f1b4Smrg cnames[np], psize, description ); 3903464ebd5Sriastradh _mesa_problem( NULL, "%s", buf ); 3917117f1b4Smrg } 3927117f1b4Smrg#ifdef RUN_DEBUG_BENCHMARK 3937117f1b4Smrg if ( mesa_profile ) 394cdc920a0Smrg printf( " %li\t", benchmark_tab[np][psize-1] ); 3957117f1b4Smrg#endif 3967117f1b4Smrg } 3977117f1b4Smrg#ifdef RUN_DEBUG_BENCHMARK 3987117f1b4Smrg if ( mesa_profile ) 399cdc920a0Smrg printf( " | [%s]\n\t", cstrings[np] ); 4007117f1b4Smrg#endif 4017117f1b4Smrg } 4027117f1b4Smrg#ifdef RUN_DEBUG_BENCHMARK 4037117f1b4Smrg if ( mesa_profile ) 404cdc920a0Smrg printf( "\n" ); 4057117f1b4Smrg#endif 4067117f1b4Smrg} 4077117f1b4Smrg 4087117f1b4Smrg 4097117f1b4Smrg#endif /* DEBUG_MATH */ 410