home *** CD-ROM | disk | FTP | other *** search
/ GameStar 2006 March / Gamestar_82_2006-03_dvd.iso / DVDStar / Editace / quake4_sdkv10.exe / source / idlib / math / Simd.cpp < prev    next >
C/C++ Source or Header  |  2005-11-14  |  123KB  |  4,343 lines

  1.  
  2. #include "../precompiled.h"
  3. #pragma hdrstop
  4.  
  5. #include "Simd_generic.h"
  6. #ifdef _WINDOWS
  7. #include "Simd_MMX.h"
  8. #include "Simd_3DNow.h"
  9. #include "Simd_SSE.h"
  10. #include "Simd_SSE2.h"
  11. #include "Simd_SSE3.h"
  12. #endif // _WINDOWS
  13. #ifdef MACOS_X
  14. #include "Simd_AltiVec.h"
  15. #endif
  16. #ifdef _XENON
  17. // RAVEN BEGIN
  18. // jsinger: Adding Xenon processor support
  19. #include "Simd_Xenon.h"
  20. // RAVEN END
  21. #endif
  22.  
  23.  
  24. idSIMDProcessor    *    processor = NULL;            // pointer to SIMD processor
  25. idSIMDProcessor *    generic = NULL;                // pointer to generic SIMD implementation
  26. idSIMDProcessor *    SIMDProcessor = NULL;
  27.  
  28.  
  29. /*
  30. ================
  31. idSIMD::Init
  32. ================
  33. */
  34. void idSIMD::Init( void ) {
  35. // RAVEN BEGIN
  36. // jnewquist: Tag scope and callees to track allocations using "new".
  37.     MEM_SCOPED_TAG(tag,MA_DEFAULT);
  38. // jsinger: xenon uses idSIMD_Xenon always
  39. #ifdef _XENON
  40.     generic = new idSIMD_Xenon;
  41. #else
  42.     generic = new idSIMD_Generic;
  43.     generic->cpuid = CPUID_GENERIC;
  44. #endif
  45. // RAVEN END
  46.     processor = NULL;
  47.     SIMDProcessor = generic;
  48. }
  49.  
  50. /*
  51. ============
  52. idSIMD::InitProcessor
  53. ============
  54. */
  55. void idSIMD::InitProcessor( const char *module, bool forceGeneric ) {
  56.     cpuid_t cpuid;
  57.     idSIMDProcessor *newProcessor;
  58.  
  59.     cpuid = idLib::sys->GetProcessorId();
  60.  
  61.     if ( forceGeneric ) {
  62.  
  63.         newProcessor = generic;
  64.  
  65.     } else {
  66.  
  67.         if ( !processor ) {
  68. // RAVEN BEGIN
  69. // jsinger: on xenon even the generic is idSIMD_Xenon so this is exactly what we want
  70. #ifdef _XENON
  71.             processor = generic;    // generic will actually be the xenon SIMD processor on xenon
  72. #else
  73.             if ( ( cpuid & CPUID_ALTIVEC ) ) {
  74. #ifdef MACOS_X
  75.                 processor = new idSIMD_AltiVec;
  76. #else
  77.                 assert( false );
  78.                 processor = generic;
  79. #endif
  80. #ifdef _WINDOWS
  81.             } else if ( ( cpuid & CPUID_MMX ) && ( cpuid & CPUID_SSE ) && ( cpuid & CPUID_SSE2 ) && ( cpuid & CPUID_SSE3 ) ) {
  82.                 processor = new idSIMD_SSE3;
  83.             } else if ( ( cpuid & CPUID_MMX ) && ( cpuid & CPUID_SSE ) && ( cpuid & CPUID_SSE2 ) ) {
  84.                 processor = new idSIMD_SSE2;
  85.             } else if ( ( cpuid & CPUID_MMX ) && ( cpuid & CPUID_SSE ) ) {
  86.                 processor = new idSIMD_SSE;
  87.             } else if ( ( cpuid & CPUID_MMX ) && ( cpuid & CPUID_3DNOW ) ) {
  88.                 processor = new idSIMD_3DNow;
  89.             } else if ( ( cpuid & CPUID_MMX ) ) {
  90.                 processor = new idSIMD_MMX;
  91. #endif // _WINDOWS
  92.             } else {
  93.                 processor = generic;
  94.             }
  95.             processor->cpuid = cpuid;
  96. #endif
  97. // RAVEN END
  98.         }
  99.  
  100.         newProcessor = processor;
  101.     }
  102.  
  103.     if ( newProcessor != SIMDProcessor ) {
  104.         SIMDProcessor = newProcessor;
  105.         idLib::common->Printf( "%s using %s for SIMD processing\n", module, SIMDProcessor->GetName() );
  106.     }
  107.  
  108.     if ( cpuid & CPUID_FTZ ) {
  109.         idLib::sys->FPU_SetFTZ( true );
  110.         idLib::common->Printf( "enabled Flush-To-Zero mode\n" );
  111.     }
  112.  
  113.     if ( cpuid & CPUID_DAZ ) {
  114.         idLib::sys->FPU_SetDAZ( true );
  115.         idLib::common->Printf( "enabled Denormals-Are-Zero mode\n" );
  116.     }
  117. }
  118.  
  119. /*
  120. ================
  121. idSIMD::Shutdown
  122. ================
  123. */
  124. void idSIMD::Shutdown( void ) {
  125.     if ( processor != generic ) {
  126.         delete processor;
  127.     }
  128.     delete generic;
  129.     generic = NULL;
  130.     processor = NULL;
  131.     SIMDProcessor = NULL;
  132. }
  133.  
  134.  
  135. //===============================================================
  136. //
  137. // Test code
  138. //
  139. //===============================================================
  140.  
  141. #define COUNT        1024        // data count
  142. #define NUMTESTS    2048        // number of tests
  143.  
  144. #define RANDOM_SEED        1013904223L    //((int)idLib::sys->GetClockTicks())
  145.  
  146. idSIMDProcessor *p_simd;
  147. idSIMDProcessor *p_generic;
  148. long baseClocks = 0;
  149.  
  150. #ifdef _WINDOWS
  151.  
  152. #define TIME_TYPE int
  153.  
  154. #pragma warning(disable : 4731)     // frame pointer register 'ebx' modified by inline assembly code
  155.  
  156. long saved_ebx = 0;
  157.  
  158. #define StartRecordTime( start )            \
  159.     __asm mov saved_ebx, ebx                \
  160.     __asm xor eax, eax                        \
  161.     __asm cpuid                                \
  162.     __asm rdtsc                                \
  163.     __asm mov start, eax                    \
  164.     __asm xor eax, eax                        \
  165.     __asm cpuid
  166.  
  167. #define StopRecordTime( end )                \
  168.     __asm xor eax, eax                        \
  169.     __asm cpuid                                \
  170.     __asm rdtsc                                \
  171.     __asm mov end, eax                        \
  172.     __asm mov ebx, saved_ebx                \
  173.     __asm xor eax, eax                        \
  174.     __asm cpuid
  175.  
  176. #elif MACOS_X
  177.  
  178. #include <stdlib.h>
  179. #include <unistd.h>            // this is for sleep()
  180. #include <sys/time.h>
  181. #include <sys/resource.h>
  182. #include <mach/mach_time.h>
  183.  
  184. double ticksPerNanosecond;
  185.  
  186. #define TIME_TYPE uint64_t
  187.  
  188. /*
  189.  
  190.     .text
  191.     .align 2
  192.     .globl _GetTB
  193. _GetTB:
  194.  
  195. loop:
  196.             mftbu   r4    ;  load from TBU
  197.             mftb    r5    ;  load from TBL
  198.             mftbu   r6    ;  load from TBU
  199.             cmpw    r6, r4    ;  see if old == new
  200.             bne     loop    ;  if not, carry occured, therefore loop
  201.  
  202.             stw     r4, 0(r3)
  203.             stw     r5, 4(r3)
  204.  
  205. done:
  206.             blr        ;  return
  207.  
  208. */
  209.  
  210. /*
  211.  
  212. typedef struct {
  213.     unsigned int hi;
  214.     unsigned int lo;
  215. } U64;
  216.  
  217. double TBToDoubleNano( U64 startTime, U64 stopTime, double ticksPerNanosecond );
  218.  
  219. #if __MWERKS__
  220. asm void GetTB( U64 * );
  221. #else
  222. void GetTB( U64 * );
  223. #endif
  224.  
  225. double TBToDoubleNano( U64 startTime, U64 stopTime, double ticksPerNanosecond ) {
  226.     #define K_2POWER32 4294967296.0
  227.     #define TICKS_PER_NANOSECOND 0.025
  228.     double nanoTime;
  229.     U64 diffTime;
  230.  
  231.     // calc the difference in TB ticks
  232.     diffTime.hi = stopTime.hi - startTime.hi;
  233.     diffTime.lo = stopTime.lo - startTime.lo;
  234.  
  235.     // convert TB ticks into time
  236.     nanoTime = (double)(diffTime.hi)*((double)K_2POWER32) + (double)(diffTime.lo);
  237.     nanoTime = nanoTime/ticksPerNanosecond;
  238.     return (nanoTime);
  239. }       
  240.  
  241. TIME_TYPE time_in_millisec( void ) {
  242.     #define K_2POWER32 4294967296.0
  243.     #define TICKS_PER_NANOSECOND 0.025
  244.  
  245.     U64 the_time;
  246.     double nanoTime, milliTime;
  247.  
  248.     GetTB( &the_time );
  249.  
  250.     // convert TB ticks into time
  251.     nanoTime = (double)(the_time.hi)*((double)K_2POWER32) + (double)(the_time.lo);
  252.     nanoTime = nanoTime/ticksPerNanosecond;
  253.  
  254.     // nanoseconds are 1 billionth of a second. I want milliseconds
  255.     milliTime = nanoTime * 1000000.0;
  256.  
  257.     printf( "ticks per nanosec -- %lf\n", ticksPerNanosecond );
  258.     printf( "nanoTime is %lf -- milliTime is %lf -- as int is %i\n", nanoTime, milliTime, (int)milliTime );
  259.  
  260.     return (int)milliTime;
  261. }
  262.  
  263. #define StartRecordTime( start )            \
  264.     start = time_in_millisec(); 
  265.  
  266. #define StopRecordTime( end )                \
  267.     end = time_in_millisec();
  268.  
  269. */
  270.  
  271. #define StartRecordTime( start )            \
  272.     start = mach_absolute_time(); 
  273.  
  274. #define StopRecordTime( end )                \
  275.     end = mach_absolute_time();
  276.  
  277. #else
  278.  
  279. #define TIME_TYPE int
  280.  
  281. #define StartRecordTime( start )            \
  282.     start = 0;
  283.  
  284. #define StopRecordTime( end )                \
  285.     end = 1;
  286.  
  287. #endif // _WINDOWS
  288.  
  289. #define GetBest( start, end, best )            \
  290.     if ( !best || end - start < best ) {    \
  291.         best = end - start;                    \
  292.     }
  293.  
  294.  
  295. /*
  296. ============
  297. PrintClocks
  298. ============
  299. */
  300. void PrintClocks( char *string, int dataCount, int clocks, int otherClocks = 0 ) {
  301.     int i;
  302.  
  303.     idLib::common->Printf( string );
  304. // RAVEN BEGIN
  305. // bdube: escape codes
  306.     for ( i = idStr::LengthWithoutEscapes(string); i < 48; i++ ) {
  307. // RAVEN END
  308.         idLib::common->Printf(" ");
  309.     }
  310.     clocks -= baseClocks;
  311.     if ( otherClocks ) {
  312.         otherClocks -= baseClocks;
  313.         int p = (int) ( (float) ( otherClocks - clocks ) * 100.0f / (float) otherClocks );
  314.         idLib::common->Printf( "c = %4d, clcks = %5d, %d%%\n", dataCount, clocks, p );
  315.     } else {
  316.         idLib::common->Printf( "c = %4d, clcks = %5d\n", dataCount, clocks );
  317.     }
  318. }
  319.  
  320. /*
  321. ============
  322. GetBaseClocks
  323. ============
  324. */
  325. void GetBaseClocks( void ) {
  326.     int i, start, end, bestClocks;
  327.  
  328.     bestClocks = 0;
  329.     for ( i = 0; i < NUMTESTS; i++ ) {
  330.         StartRecordTime( start );
  331.         StopRecordTime( end );
  332.         GetBest( start, end, bestClocks );
  333.     }
  334.     baseClocks = bestClocks;
  335. }
  336.  
  337. /*
  338. ============
  339. TestAdd
  340. ============
  341. */
  342. void TestAdd( void ) {
  343.     int i;
  344.     TIME_TYPE start, end, bestClocksGeneric, bestClocksSIMD;
  345.     ALIGN16( float fdst0[COUNT]; )
  346.     ALIGN16( float fdst1[COUNT]; )
  347.     ALIGN16( float fsrc0[COUNT]; )
  348.     ALIGN16( float fsrc1[COUNT]; )
  349.     const char *result;
  350.  
  351.     idRandom srnd( RANDOM_SEED );
  352.  
  353.     for ( i = 0; i < COUNT; i++ ) {
  354.         fsrc0[i] = srnd.CRandomFloat() * 10.0f;
  355.         fsrc1[i] = srnd.CRandomFloat() * 10.0f;
  356.     }
  357.  
  358.     idLib::common->Printf("====================================\n" );
  359.  
  360.     bestClocksGeneric = 0;
  361.     for ( i = 0; i < NUMTESTS; i++ ) {
  362.         StartRecordTime( start );
  363.         p_generic->Add( fdst0, 4.0f, fsrc1, COUNT );
  364.         StopRecordTime( end );
  365.         GetBest( start, end, bestClocksGeneric );
  366.     }
  367.     PrintClocks( "generic->Add( float + float[] )", COUNT, bestClocksGeneric );
  368.  
  369.     bestClocksSIMD = 0;
  370.     for ( i = 0; i < NUMTESTS; i++ ) {
  371.         StartRecordTime( start );
  372.         p_simd->Add( fdst1, 4.0f, fsrc1, COUNT );
  373.         StopRecordTime( end );
  374.         GetBest( start, end, bestClocksSIMD );
  375.     }
  376.  
  377.     for ( i = 0; i < COUNT; i++ ) {
  378.         if ( idMath::Fabs( fdst0[i] - fdst1[i] ) > 1e-5f ) {
  379.             break;
  380.         }
  381.     }
  382.     result = ( i >= COUNT ) ? "ok" : S_COLOR_RED"X";
  383.     PrintClocks( va( "   simd->Add( float + float[] ) %s", result ), COUNT, bestClocksSIMD, bestClocksGeneric );
  384.  
  385.     bestClocksGeneric = 0;
  386.     for ( i = 0; i < NUMTESTS; i++ ) {
  387.         StartRecordTime( start );
  388.         p_generic->Add( fdst0, fsrc0, fsrc1, COUNT );
  389.         StopRecordTime( end );
  390.         GetBest( start, end, bestClocksGeneric );
  391.     }
  392.     PrintClocks( "generic->Add( float[] + float[] )", COUNT, bestClocksGeneric );
  393.  
  394.     bestClocksSIMD = 0;
  395.     for ( i = 0; i < NUMTESTS; i++ ) {
  396.         StartRecordTime( start );
  397.         p_simd->Add( fdst1, fsrc0, fsrc1, COUNT );
  398.         StopRecordTime( end );
  399.         GetBest( start, end, bestClocksSIMD );
  400.     }
  401.  
  402.     for ( i = 0; i < COUNT; i++ ) {
  403.         if ( idMath::Fabs( fdst0[i] - fdst1[i] ) > 1e-5f ) {
  404.             break;
  405.         }
  406.     }
  407.     result = ( i >= COUNT ) ? "ok" : S_COLOR_RED"X";
  408.     PrintClocks( va( "   simd->Add( float[] + float[] ) %s", result ), COUNT, bestClocksSIMD, bestClocksGeneric );
  409. }
  410.  
  411. /*
  412. ============
  413. TestSub
  414. ============
  415. */
  416. void TestSub( void ) {
  417.     int i;
  418.     TIME_TYPE start, end, bestClocksGeneric, bestClocksSIMD;
  419.     ALIGN16( float fdst0[COUNT]; )
  420.     ALIGN16( float fdst1[COUNT]; )
  421.     ALIGN16( float fsrc0[COUNT]; )
  422.     ALIGN16( float fsrc1[COUNT]; )
  423.     const char *result;
  424.  
  425.     idRandom srnd( RANDOM_SEED );
  426.  
  427.     for ( i = 0; i < COUNT; i++ ) {
  428.         fsrc0[i] = srnd.CRandomFloat() * 10.0f;
  429.         fsrc1[i] = srnd.CRandomFloat() * 10.0f;
  430.     }
  431.  
  432.     idLib::common->Printf("====================================\n" );
  433.  
  434.     bestClocksGeneric = 0;
  435.     for ( i = 0; i < NUMTESTS; i++ ) {
  436.         StartRecordTime( start );
  437.         p_generic->Sub( fdst0, 4.0f, fsrc1, COUNT );
  438.         StopRecordTime( end );
  439.         GetBest( start, end, bestClocksGeneric );
  440.     }
  441.     PrintClocks( "generic->Sub( float + float[] )", COUNT, bestClocksGeneric );
  442.  
  443.     bestClocksSIMD = 0;
  444.     for ( i = 0; i < NUMTESTS; i++ ) {
  445.         StartRecordTime( start );
  446.         p_simd->Sub( fdst1, 4.0f, fsrc1, COUNT );
  447.         StopRecordTime( end );
  448.         GetBest( start, end, bestClocksSIMD );
  449.     }
  450.  
  451.     for ( i = 0; i < COUNT; i++ ) {
  452.         if ( idMath::Fabs( fdst0[i] - fdst1[i] ) > 1e-5f ) {
  453.             break;
  454.         }
  455.     }
  456.     result = ( i >= COUNT ) ? "ok" : S_COLOR_RED"X";
  457.     PrintClocks( va( "   simd->Sub( float + float[] ) %s", result ), COUNT, bestClocksSIMD, bestClocksGeneric );
  458.  
  459.     bestClocksGeneric = 0;
  460.     for ( i = 0; i < NUMTESTS; i++ ) {
  461.         StartRecordTime( start );
  462.         p_generic->Sub( fdst0, fsrc0, fsrc1, COUNT );
  463.         StopRecordTime( end );
  464.         GetBest( start, end, bestClocksGeneric );
  465.     }
  466.     PrintClocks( "generic->Sub( float[] + float[] )", COUNT, bestClocksGeneric );
  467.  
  468.     bestClocksSIMD = 0;
  469.     for ( i = 0; i < NUMTESTS; i++ ) {
  470.         StartRecordTime( start );
  471.         p_simd->Sub( fdst1, fsrc0, fsrc1, COUNT );
  472.         StopRecordTime( end );
  473.         GetBest( start, end, bestClocksSIMD );
  474.     }
  475.  
  476.     for ( i = 0; i < COUNT; i++ ) {
  477.         if ( idMath::Fabs( fdst0[i] - fdst1[i] ) > 1e-5f ) {
  478.             break;
  479.         }
  480.     }
  481.     result = ( i >= COUNT ) ? "ok" : S_COLOR_RED"X";
  482.     PrintClocks( va( "   simd->Sub( float[] + float[] ) %s", result ), COUNT, bestClocksSIMD, bestClocksGeneric );
  483. }
  484.  
  485. /*
  486. ============
  487. TestMul
  488. ============
  489. */
  490. void TestMul( void ) {
  491.     int i;
  492.     TIME_TYPE start, end, bestClocksGeneric, bestClocksSIMD;
  493.     ALIGN16( float fdst0[COUNT]; )
  494.     ALIGN16( float fdst1[COUNT]; )
  495.     ALIGN16( float fsrc0[COUNT]; )
  496.     ALIGN16( float fsrc1[COUNT]; )
  497.     const char *result;
  498.  
  499.     idRandom srnd( RANDOM_SEED );
  500.  
  501.     for ( i = 0; i < COUNT; i++ ) {
  502.         fsrc0[i] = srnd.CRandomFloat() * 10.0f;
  503.         fsrc1[i] = srnd.CRandomFloat() * 10.0f;
  504.     }
  505.  
  506.     idLib::common->Printf("====================================\n" );
  507.  
  508.     bestClocksGeneric = 0;
  509.     for ( i = 0; i < NUMTESTS; i++ ) {
  510.         StartRecordTime( start );
  511.         p_generic->Mul( fdst0, 4.0f, fsrc1, COUNT );
  512.         StopRecordTime( end );
  513.         GetBest( start, end, bestClocksGeneric );
  514.     }
  515.     PrintClocks( "generic->Mul( float * float[] )", COUNT, bestClocksGeneric );
  516.  
  517.     bestClocksSIMD = 0;
  518.     for ( i = 0; i < NUMTESTS; i++ ) {
  519.         StartRecordTime( start );
  520.         p_simd->Mul( fdst1, 4.0f, fsrc1, COUNT );
  521.         StopRecordTime( end );
  522.         GetBest( start, end, bestClocksSIMD );
  523.     }
  524.  
  525.     for ( i = 0; i < COUNT; i++ ) {
  526.         if ( idMath::Fabs( fdst0[i] - fdst1[i] ) > 1e-5f ) {
  527.             break;
  528.         }
  529.     }
  530.     result = ( i >= COUNT ) ? "ok" : S_COLOR_RED"X";
  531.     PrintClocks( va( "   simd->Mul( float * float[] ) %s", result ), COUNT, bestClocksSIMD, bestClocksGeneric );
  532.  
  533.  
  534.     bestClocksGeneric = 0;
  535.     for ( i = 0; i < NUMTESTS; i++ ) {
  536.         StartRecordTime( start );
  537.         p_generic->Mul( fdst0, fsrc0, fsrc1, COUNT );
  538.         StopRecordTime( end );
  539.         GetBest( start, end, bestClocksGeneric );
  540.     }
  541.     PrintClocks( "generic->Mul( float[] * float[] )", COUNT, bestClocksGeneric );
  542.  
  543.     bestClocksSIMD = 0;
  544.     for ( i = 0; i < NUMTESTS; i++ ) {
  545.         StartRecordTime( start );
  546.         p_simd->Mul( fdst1, fsrc0, fsrc1, COUNT );
  547.         StopRecordTime( end );
  548.         GetBest( start, end, bestClocksSIMD );
  549.     }
  550.  
  551.     for ( i = 0; i < COUNT; i++ ) {
  552.         if ( idMath::Fabs( fdst0[i] - fdst1[i] ) > 1e-5f ) {
  553.             break;
  554.         }
  555.     }
  556.     result = ( i >= COUNT ) ? "ok" : S_COLOR_RED"X";
  557.     PrintClocks( va( "   simd->Mul( float[] * float[] ) %s", result ), COUNT, bestClocksSIMD, bestClocksGeneric );
  558. }
  559.  
  560. /*
  561. ============
  562. TestDiv
  563. ============
  564. */
  565. void TestDiv( void ) {
  566.     int i;
  567.     TIME_TYPE start, end, bestClocksGeneric, bestClocksSIMD;
  568.     ALIGN16( float fdst0[COUNT]; )
  569.     ALIGN16( float fdst1[COUNT]; )
  570.     ALIGN16( float fsrc0[COUNT]; )
  571.     ALIGN16( float fsrc1[COUNT]; )
  572.     const char *result;
  573.  
  574.     idRandom srnd( RANDOM_SEED );
  575.  
  576.     for ( i = 0; i < COUNT; i++ ) {
  577.         fsrc0[i] = srnd.CRandomFloat() * 10.0f;
  578.         do {
  579.             fsrc1[i] = srnd.CRandomFloat() * 10.0f;
  580.         } while( idMath::Fabs( fsrc1[i] ) < 0.1f );
  581.     }
  582.  
  583.     idLib::common->Printf("====================================\n" );
  584.  
  585.  
  586.     bestClocksGeneric = 0;
  587.     for ( i = 0; i < NUMTESTS; i++ ) {
  588.         StartRecordTime( start );
  589.         p_generic->Div( fdst0, 4.0f, fsrc1, COUNT );
  590.         StopRecordTime( end );
  591.         GetBest( start, end, bestClocksGeneric );
  592.     }
  593.     PrintClocks( "generic->Div( float * float[] )", COUNT, bestClocksGeneric );
  594.  
  595.     bestClocksSIMD = 0;
  596.     for ( i = 0; i < NUMTESTS; i++ ) {
  597.         StartRecordTime( start );
  598.         p_simd->Div( fdst1, 4.0f, fsrc1, COUNT );
  599.         StopRecordTime( end );
  600.         GetBest( start, end, bestClocksSIMD );
  601.     }
  602.  
  603.     for ( i = 0; i < COUNT; i++ ) {
  604.         if ( idMath::Fabs( fdst0[i] - fdst1[i] ) > 1e-5f ) {
  605.             break;
  606.         }
  607.     }
  608.     result = ( i >= COUNT ) ? "ok" : S_COLOR_RED"X";
  609.     PrintClocks( va( "   simd->Div( float * float[] ) %s", result ), COUNT, bestClocksSIMD, bestClocksGeneric );
  610.  
  611.  
  612.     bestClocksGeneric = 0;
  613.     for ( i = 0; i < NUMTESTS; i++ ) {
  614.         StartRecordTime( start );
  615.         p_generic->Div( fdst0, fsrc0, fsrc1, COUNT );
  616.         StopRecordTime( end );
  617.         GetBest( start, end, bestClocksGeneric );
  618.     }
  619.     PrintClocks( "generic->Div( float[] * float[] )", COUNT, bestClocksGeneric );
  620.  
  621.     bestClocksSIMD = 0;
  622.     for ( i = 0; i < NUMTESTS; i++ ) {
  623.         StartRecordTime( start );
  624.         p_simd->Div( fdst1, fsrc0, fsrc1, COUNT );
  625.         StopRecordTime( end );
  626.         GetBest( start, end, bestClocksSIMD );
  627.     }
  628.  
  629.     for ( i = 0; i < COUNT; i++ ) {
  630.         if ( idMath::Fabs( fdst0[i] - fdst1[i] ) > 1e-3f ) {
  631.             break;
  632.         }
  633.     }
  634.     result = ( i >= COUNT ) ? "ok" : S_COLOR_RED"X";
  635.     PrintClocks( va( "   simd->Div( float[] * float[] ) %s", result ), COUNT, bestClocksSIMD, bestClocksGeneric );
  636. }
  637.  
  638. /*
  639. ============
  640. TestMulAdd
  641. ============
  642. */
  643. void TestMulAdd( void ) {
  644.     int i, j;
  645.     TIME_TYPE start, end, bestClocksGeneric, bestClocksSIMD;
  646.     ALIGN16( float fdst0[COUNT]; )
  647.     ALIGN16( float fdst1[COUNT]; )
  648.     ALIGN16( float fsrc0[COUNT]; )
  649.     const char *result;
  650.  
  651.     idRandom srnd( RANDOM_SEED );
  652.  
  653.     for ( i = 0; i < COUNT; i++ ) {
  654.         fsrc0[i] = srnd.CRandomFloat() * 10.0f;
  655.     }
  656.  
  657.     idLib::common->Printf("====================================\n" );
  658.  
  659.     for ( j = 0; j < 50 && j < COUNT; j++ ) {
  660.  
  661.         bestClocksGeneric = 0;
  662.         for ( i = 0; i < NUMTESTS; i++ ) {
  663.             for ( int k = 0; k < COUNT; k++ ) {
  664.                 fdst0[k] = k;
  665.             }
  666.             StartRecordTime( start );
  667.             p_generic->MulAdd( fdst0, 0.123f, fsrc0, j );
  668.             StopRecordTime( end );
  669.             GetBest( start, end, bestClocksGeneric );
  670.         }
  671.         PrintClocks( va( "generic->MulAdd( float * float[%2d] )", j ), 1, bestClocksGeneric );
  672.  
  673.         bestClocksSIMD = 0;
  674.         for ( i = 0; i < NUMTESTS; i++ ) {
  675.             for ( int k = 0; k < COUNT; k++ ) {
  676.                 fdst1[k] = k;
  677.             }
  678.             StartRecordTime( start );
  679.             p_simd->MulAdd( fdst1, 0.123f, fsrc0, j );
  680.             StopRecordTime( end );
  681.             GetBest( start, end, bestClocksSIMD );
  682.         }
  683.  
  684.         for ( i = 0; i < COUNT; i++ ) {
  685.             if ( idMath::Fabs( fdst0[i] - fdst1[i] ) > 1e-5f ) {
  686.                 break;
  687.             }
  688.         }
  689.         result = ( i >= COUNT ) ? "ok" : S_COLOR_RED"X";
  690.         PrintClocks( va( "   simd->MulAdd( float * float[%2d] ) %s", j, result ), 1, bestClocksSIMD, bestClocksGeneric );
  691.     }
  692. }
  693.  
  694. /*
  695. ============
  696. TestMulSub
  697. ============
  698. */
  699. void TestMulSub( void ) {
  700.     int i, j;
  701.     TIME_TYPE start, end, bestClocksGeneric, bestClocksSIMD;
  702.     ALIGN16( float fdst0[COUNT]; )
  703.     ALIGN16( float fdst1[COUNT]; )
  704.     ALIGN16( float fsrc0[COUNT]; )
  705.     const char *result;
  706.  
  707.     idRandom srnd( RANDOM_SEED );
  708.  
  709.     for ( i = 0; i < COUNT; i++ ) {
  710.         fsrc0[i] = srnd.CRandomFloat() * 10.0f;
  711.     }
  712.  
  713.     idLib::common->Printf("====================================\n" );
  714.  
  715.     for ( j = 0; j < 50 && j < COUNT; j++ ) {
  716.  
  717.         bestClocksGeneric = 0;
  718.         for ( i = 0; i < NUMTESTS; i++ ) {
  719.             for ( int k = 0; k < COUNT; k++ ) {
  720.                 fdst0[k] = k;
  721.             }
  722.             StartRecordTime( start );
  723.             p_generic->MulSub( fdst0, 0.123f, fsrc0, j );
  724.             StopRecordTime( end );
  725.             GetBest( start, end, bestClocksGeneric );
  726.         }
  727.         PrintClocks( va( "generic->MulSub( float * float[%2d] )", j ), 1, bestClocksGeneric );
  728.  
  729.         bestClocksSIMD = 0;
  730.         for ( i = 0; i < NUMTESTS; i++ ) {
  731.             for ( int k = 0; k < COUNT; k++ ) {
  732.                 fdst1[k] = k;
  733.             }
  734.             StartRecordTime( start );
  735.             p_simd->MulSub( fdst1, 0.123f, fsrc0, j );
  736.             StopRecordTime( end );
  737.             GetBest( start, end, bestClocksSIMD );
  738.         }
  739.  
  740.         for ( i = 0; i < COUNT; i++ ) {
  741.             if ( idMath::Fabs( fdst0[i] - fdst1[i] ) > 1e-5f ) {
  742.                 break;
  743.             }
  744.         }
  745.         result = ( i >= COUNT ) ? "ok" : S_COLOR_RED"X";
  746.         PrintClocks( va( "   simd->MulSub( float * float[%2d] ) %s", j, result ), 1, bestClocksSIMD, bestClocksGeneric );
  747.     }
  748. }
  749.  
  750. /*
  751. ============
  752. TestDot
  753. ============
  754. */
  755. void TestDot( void ) {
  756.     int i, j;
  757.     TIME_TYPE start, end, bestClocksGeneric, bestClocksSIMD;
  758.     ALIGN16( float fdst0[COUNT]; )
  759.     ALIGN16( float fdst1[COUNT]; )
  760.     ALIGN16( float fsrc0[COUNT]; )
  761.     ALIGN16( float fsrc1[COUNT]; )
  762.     ALIGN16( idVec3 v3src0[COUNT]; )
  763.     ALIGN16( idVec3 v3src1[COUNT]; )
  764.     ALIGN16( idVec3 v3constant( 1.0f, 2.0f, 3.0f ); )
  765.     ALIGN16( idPlane v4src0[COUNT]; )
  766.     ALIGN16( idPlane v4constant(1.0f, 2.0f, 3.0f, 4.0f); )
  767.     ALIGN16( idDrawVert drawVerts[COUNT]; )
  768.     const char *result;
  769.  
  770.     idRandom srnd( RANDOM_SEED );
  771.  
  772.     for ( i = 0; i < COUNT; i++ ) {
  773.         fsrc0[i] = srnd.CRandomFloat() * 10.0f;
  774.         fsrc1[i] = srnd.CRandomFloat() * 10.0f;
  775.         for ( j = 0; j < 3; j++ ) {
  776.             v3src0[i][j] = srnd.CRandomFloat() * 10.0f;
  777.             v3src1[i][j] = srnd.CRandomFloat() * 10.0f;
  778.         }
  779.         v4src0[i] = v3src0[i];
  780.         v4src0[i][3] = srnd.CRandomFloat() * 10.0f;
  781.         drawVerts[i].xyz = v3src0[i];
  782.     }
  783.  
  784.     idLib::common->Printf("====================================\n" );
  785.  
  786.  
  787.     bestClocksGeneric = 0;
  788.     for ( i = 0; i < NUMTESTS; i++ ) {
  789.         StartRecordTime( start );
  790.         p_generic->Dot( fdst0, v3constant, v3src0, COUNT );
  791.         StopRecordTime( end );
  792.         GetBest( start, end, bestClocksGeneric );
  793.     }
  794.     PrintClocks( "generic->Dot( idVec3 * idVec3[] )", COUNT, bestClocksGeneric );
  795.  
  796.     bestClocksSIMD = 0;
  797.     for ( i = 0; i < NUMTESTS; i++ ) {
  798.         StartRecordTime( start );
  799.         p_simd->Dot( fdst1, v3constant, v3src0, COUNT );
  800.         StopRecordTime( end );
  801.         GetBest( start, end, bestClocksSIMD );
  802.     }
  803.  
  804.     for ( i = 0; i < COUNT; i++ ) {
  805.         if ( idMath::Fabs( fdst0[i] - fdst1[i] ) > 1e-5f ) {
  806.             break;
  807.         }
  808.     }
  809.     result = ( i >= COUNT ) ? "ok" : S_COLOR_RED"X";
  810.     PrintClocks( va( "   simd->Dot( idVec3 * idVec3[] ) %s", result ), COUNT, bestClocksSIMD, bestClocksGeneric );
  811.  
  812.  
  813.     bestClocksGeneric = 0;
  814.     for ( i = 0; i < NUMTESTS; i++ ) {
  815.         StartRecordTime( start );
  816.         p_generic->Dot( fdst0, v3constant, v4src0, COUNT );
  817.         StopRecordTime( end );
  818.         GetBest( start, end, bestClocksGeneric );
  819.     }
  820.     PrintClocks( "generic->Dot( idVec3 * idPlane[] )", COUNT, bestClocksGeneric );
  821.  
  822.     bestClocksSIMD = 0;
  823.     for ( i = 0; i < NUMTESTS; i++ ) {
  824.         StartRecordTime( start );
  825.         p_simd->Dot( fdst1, v3constant, v4src0, COUNT );
  826.         StopRecordTime( end );
  827.         GetBest( start, end, bestClocksSIMD );
  828.     }
  829.  
  830.     for ( i = 0; i < COUNT; i++ ) {
  831.         if ( idMath::Fabs( fdst0[i] - fdst1[i] ) > 1e-5f ) {
  832.             break;
  833.         }
  834.     }
  835.     result = ( i >= COUNT ) ? "ok" : S_COLOR_RED"X";
  836.     PrintClocks( va( "   simd->Dot( idVec3 * idPlane[] ) %s", result ), COUNT, bestClocksSIMD, bestClocksGeneric );
  837.  
  838.  
  839.     bestClocksGeneric = 0;
  840.     for ( i = 0; i < NUMTESTS; i++ ) {
  841.         StartRecordTime( start );
  842.         p_generic->Dot( fdst0, v3constant, drawVerts, COUNT );
  843.         StopRecordTime( end );
  844.         GetBest( start, end, bestClocksGeneric );
  845.     }
  846.     PrintClocks( "generic->Dot( idVec3 * idDrawVert[] )", COUNT, bestClocksGeneric );
  847.  
  848.     bestClocksSIMD = 0;
  849.     for ( i = 0; i < NUMTESTS; i++ ) {
  850.         StartRecordTime( start );
  851.         p_simd->Dot( fdst1, v3constant, drawVerts, COUNT );
  852.         StopRecordTime( end );
  853.         GetBest( start, end, bestClocksSIMD );
  854.     }
  855.  
  856.     for ( i = 0; i < COUNT; i++ ) {
  857.         if ( idMath::Fabs( fdst0[i] - fdst1[i] ) > 1e-5f ) {
  858.             break;
  859.         }
  860.     }
  861.     result = ( i >= COUNT ) ? "ok" : S_COLOR_RED"X";
  862.     PrintClocks( va( "   simd->Dot( idVec3 * idDrawVert[] ) %s", result ), COUNT, bestClocksSIMD, bestClocksGeneric );
  863.  
  864.  
  865.     bestClocksGeneric = 0;
  866.     for ( i = 0; i < NUMTESTS; i++ ) {
  867.         StartRecordTime( start );
  868.         p_generic->Dot( fdst0, v4constant, v3src0, COUNT );
  869.         StopRecordTime( end );
  870.         GetBest( start, end, bestClocksGeneric );
  871.     }
  872.     PrintClocks( "generic->Dot( idPlane * idVec3[] )", COUNT, bestClocksGeneric );
  873.  
  874.     bestClocksSIMD = 0;
  875.     for ( i = 0; i < NUMTESTS; i++ ) {
  876.         StartRecordTime( start );
  877.         p_simd->Dot( fdst1, v4constant, v3src0, COUNT );
  878.         StopRecordTime( end );
  879.         GetBest( start, end, bestClocksSIMD );
  880.     }
  881.  
  882.     for ( i = 0; i < COUNT; i++ ) {
  883.         if ( idMath::Fabs( fdst0[i] - fdst1[i] ) > 1e-5f ) {
  884.             break;
  885.         }
  886.     }
  887.     result = ( i >= COUNT ) ? "ok" : S_COLOR_RED"X";
  888.     PrintClocks( va( "   simd->Dot( idPlane * idVec3[] ) %s", result ), COUNT, bestClocksSIMD, bestClocksGeneric );
  889.  
  890.  
  891.     bestClocksGeneric = 0;
  892.     for ( i = 0; i < NUMTESTS; i++ ) {
  893.         StartRecordTime( start );
  894.         p_generic->Dot( fdst0, v4constant, v4src0, COUNT );
  895.         StopRecordTime( end );
  896.         GetBest( start, end, bestClocksGeneric );
  897.     }
  898.     PrintClocks( "generic->Dot( idPlane * idPlane[] )", COUNT, bestClocksGeneric );
  899.  
  900.     bestClocksSIMD = 0;
  901.     for ( i = 0; i < NUMTESTS; i++ ) {
  902.         StartRecordTime( start );
  903.         p_simd->Dot( fdst1, v4constant, v4src0, COUNT );
  904.         StopRecordTime( end );
  905.         GetBest( start, end, bestClocksSIMD );
  906.     }
  907.  
  908.     for ( i = 0; i < COUNT; i++ ) {
  909.         if ( idMath::Fabs( fdst0[i] - fdst1[i] ) > 1e-5f ) {
  910.             break;
  911.         }
  912.     }
  913.     result = ( i >= COUNT ) ? "ok" : S_COLOR_RED"X";
  914.     PrintClocks( va( "   simd->Dot( idPlane * idPlane[] ) %s", result ), COUNT, bestClocksSIMD, bestClocksGeneric );
  915.  
  916.  
  917.     bestClocksGeneric = 0;
  918.     for ( i = 0; i < NUMTESTS; i++ ) {
  919.         StartRecordTime( start );
  920.         p_generic->Dot( fdst0, v4constant, drawVerts, COUNT );
  921.         StopRecordTime( end );
  922.         GetBest( start, end, bestClocksGeneric );
  923.     }
  924.     PrintClocks( "generic->Dot( idPlane * idDrawVert[] )", COUNT, bestClocksGeneric );
  925.  
  926.     bestClocksSIMD = 0;
  927.     for ( i = 0; i < NUMTESTS; i++ ) {
  928.         StartRecordTime( start );
  929.         p_simd->Dot( fdst1, v4constant, drawVerts, COUNT );
  930.         StopRecordTime( end );
  931.         GetBest( start, end, bestClocksSIMD );
  932.     }
  933.  
  934.     for ( i = 0; i < COUNT; i++ ) {
  935.         if ( idMath::Fabs( fdst0[i] - fdst1[i] ) > 1e-5f ) {
  936.             break;
  937.         }
  938.     }
  939.     result = ( i >= COUNT ) ? "ok" : S_COLOR_RED"X";
  940.     PrintClocks( va( "   simd->Dot( idPlane * idDrawVert[] ) %s", result ), COUNT, bestClocksSIMD, bestClocksGeneric );
  941.  
  942.  
  943.     bestClocksGeneric = 0;
  944.     for ( i = 0; i < NUMTESTS; i++ ) {
  945.         StartRecordTime( start );
  946.         p_generic->Dot( fdst0, v3src0, v3src1, COUNT );
  947.         StopRecordTime( end );
  948.         GetBest( start, end, bestClocksGeneric );
  949.     }
  950.     PrintClocks( "generic->Dot( idVec3[] * idVec3[] )", COUNT, bestClocksGeneric );
  951.  
  952.     bestClocksSIMD = 0;
  953.     for ( i = 0; i < NUMTESTS; i++ ) {
  954.         StartRecordTime( start );
  955.         p_simd->Dot( fdst1, v3src0, v3src1, COUNT );
  956.         StopRecordTime( end );
  957.         GetBest( start, end, bestClocksSIMD );
  958.     }
  959.  
  960.     for ( i = 0; i < COUNT; i++ ) {
  961.         if ( idMath::Fabs( fdst0[i] - fdst1[i] ) > 1e-4f ) {
  962.             break;
  963.         }
  964.     }
  965.     result = ( i >= COUNT ) ? "ok" : S_COLOR_RED"X";
  966.     PrintClocks( va( "   simd->Dot( idVec3[] * idVec3[] ) %s", result ), COUNT, bestClocksSIMD, bestClocksGeneric );
  967.  
  968.  
  969.     idLib::common->Printf("====================================\n" );
  970.  
  971.     float dot1 = 0.0f, dot2 = 0.0f;
  972.     for ( j = 0; j < 50 && j < COUNT; j++ ) {
  973.  
  974.         bestClocksGeneric = 0;
  975.         for ( i = 0; i < NUMTESTS; i++ ) {
  976.             StartRecordTime( start );
  977.             p_generic->Dot( dot1, fsrc0, fsrc1, j );
  978.             StopRecordTime( end );
  979.             GetBest( start, end, bestClocksGeneric );
  980.         }
  981.         PrintClocks( va( "generic->Dot( float[%2d] * float[%2d] )", j, j ), 1, bestClocksGeneric );
  982.  
  983.         bestClocksSIMD = 0;
  984.         for ( i = 0; i < NUMTESTS; i++ ) {
  985.             StartRecordTime( start );
  986.             p_simd->Dot( dot2, fsrc0, fsrc1, j );
  987.             StopRecordTime( end );
  988.             GetBest( start, end, bestClocksSIMD );
  989.         }
  990.         result = idMath::Fabs( dot1 - dot2 ) < 1e-4f ? "ok" : S_COLOR_RED"X";
  991.         PrintClocks( va( "   simd->Dot( float[%2d] * float[%2d] ) %s", j, j, result ), 1, bestClocksSIMD, bestClocksGeneric );
  992.     }
  993. }
  994.  
  995. /*
  996. ============
  997. TestCompare
  998. ============
  999. */
  1000. void TestCompare( void ) {
  1001.     int i;
  1002.     TIME_TYPE start, end, bestClocksGeneric, bestClocksSIMD;
  1003.     ALIGN16( float fsrc0[COUNT]; )
  1004.     ALIGN16( byte bytedst[COUNT]; )
  1005.     ALIGN16( byte bytedst2[COUNT]; )
  1006.     const char *result;
  1007.  
  1008.     idRandom srnd( RANDOM_SEED );
  1009.  
  1010.     for ( i = 0; i < COUNT; i++ ) {
  1011.         fsrc0[i] = srnd.CRandomFloat() * 10.0f;
  1012.     }
  1013.  
  1014.     idLib::common->Printf("====================================\n" );
  1015.  
  1016.     bestClocksGeneric = 0;
  1017.     for ( i = 0; i < NUMTESTS; i++ ) {
  1018.         StartRecordTime( start );
  1019.         p_generic->CmpGT( bytedst, fsrc0, 0.0f, COUNT );
  1020.         StopRecordTime( end );
  1021.         GetBest( start, end, bestClocksGeneric );
  1022.     }
  1023.     PrintClocks( "generic->CmpGT( float[] >= float )", COUNT, bestClocksGeneric );
  1024.  
  1025.     bestClocksSIMD = 0;
  1026.     for ( i = 0; i < NUMTESTS; i++ ) {
  1027.         StartRecordTime( start );
  1028.         p_simd->CmpGT( bytedst2, fsrc0, 0.0f, COUNT );
  1029.         StopRecordTime( end );
  1030.         GetBest( start, end, bestClocksSIMD );
  1031.     }
  1032.  
  1033.     for ( i = 0; i < COUNT; i++ ) {
  1034.         if ( bytedst[i] != bytedst2[i] ) {
  1035.             break;
  1036.         }
  1037.     }
  1038.     result = ( i >= COUNT ) ? "ok" : S_COLOR_RED"X";
  1039.     PrintClocks( va( "   simd->CmpGT( float[] >= float ) %s", result ), COUNT, bestClocksSIMD, bestClocksGeneric );
  1040.  
  1041.     bestClocksGeneric = 0;
  1042.     for ( i = 0; i < NUMTESTS; i++ ) {
  1043.         memset( bytedst, 0, COUNT );
  1044.         StartRecordTime( start );
  1045.         p_generic->CmpGT( bytedst, 2, fsrc0, 0.0f, COUNT );
  1046.         StopRecordTime( end );
  1047.         GetBest( start, end, bestClocksGeneric );
  1048.     }
  1049.     PrintClocks( "generic->CmpGT( 2, float[] >= float )", COUNT, bestClocksGeneric );
  1050.  
  1051.     bestClocksSIMD = 0;
  1052.     for ( i = 0; i < NUMTESTS; i++ ) {
  1053.         memset( bytedst2, 0, COUNT );
  1054.         StartRecordTime( start );
  1055.         p_simd->CmpGT( bytedst2, 2, fsrc0, 0.0f, COUNT );
  1056.         StopRecordTime( end );
  1057.         GetBest( start, end, bestClocksSIMD );
  1058.     }
  1059.  
  1060.     for ( i = 0; i < COUNT; i++ ) {
  1061.         if ( bytedst[i] != bytedst2[i] ) {
  1062.             break;
  1063.         }
  1064.     }
  1065.     result = ( i >= COUNT ) ? "ok" : S_COLOR_RED"X";
  1066.     PrintClocks( va( "   simd->CmpGT( 2, float[] >= float ) %s", result ), COUNT, bestClocksSIMD, bestClocksGeneric );
  1067.  
  1068.     // ======================
  1069.  
  1070.     bestClocksGeneric = 0;
  1071.     for ( i = 0; i < NUMTESTS; i++ ) {
  1072.         StartRecordTime( start );
  1073.         p_generic->CmpGE( bytedst, fsrc0, 0.0f, COUNT );
  1074.         StopRecordTime( end );
  1075.         GetBest( start, end, bestClocksGeneric );
  1076.     }
  1077.     PrintClocks( "generic->CmpGE( float[] >= float )", COUNT, bestClocksGeneric );
  1078.  
  1079.     bestClocksSIMD = 0;
  1080.     for ( i = 0; i < NUMTESTS; i++ ) {
  1081.         StartRecordTime( start );
  1082.         p_simd->CmpGE( bytedst2, fsrc0, 0.0f, COUNT );
  1083.         StopRecordTime( end );
  1084.         GetBest( start, end, bestClocksSIMD );
  1085.     }
  1086.  
  1087.     for ( i = 0; i < COUNT; i++ ) {
  1088.         if ( bytedst[i] != bytedst2[i] ) {
  1089.             break;
  1090.         }
  1091.     }
  1092.     result = ( i >= COUNT ) ? "ok" : S_COLOR_RED"X";
  1093.     PrintClocks( va( "   simd->CmpGE( float[] >= float ) %s", result ), COUNT, bestClocksSIMD, bestClocksGeneric );
  1094.  
  1095.     bestClocksGeneric = 0;
  1096.     for ( i = 0; i < NUMTESTS; i++ ) {
  1097.         memset( bytedst, 0, COUNT );
  1098.         StartRecordTime( start );
  1099.         p_generic->CmpGE( bytedst, 2, fsrc0, 0.0f, COUNT );
  1100.         StopRecordTime( end );
  1101.         GetBest( start, end, bestClocksGeneric );
  1102.     }
  1103.     PrintClocks( "generic->CmpGE( 2, float[] >= float )", COUNT, bestClocksGeneric );
  1104.  
  1105.     bestClocksSIMD = 0;
  1106.     for ( i = 0; i < NUMTESTS; i++ ) {
  1107.         memset( bytedst2, 0, COUNT );
  1108.         StartRecordTime( start );
  1109.         p_simd->CmpGE( bytedst2, 2, fsrc0, 0.0f, COUNT );
  1110.         StopRecordTime( end );
  1111.         GetBest( start, end, bestClocksSIMD );
  1112.     }
  1113.  
  1114.     for ( i = 0; i < COUNT; i++ ) {
  1115.         if ( bytedst[i] != bytedst2[i] ) {
  1116.             break;
  1117.         }
  1118.     }
  1119.     result = ( i >= COUNT ) ? "ok" : S_COLOR_RED"X";
  1120.     PrintClocks( va( "   simd->CmpGE( 2, float[] >= float ) %s", result ), COUNT, bestClocksSIMD, bestClocksGeneric );
  1121.  
  1122.     // ======================
  1123.  
  1124.     bestClocksGeneric = 0;
  1125.     for ( i = 0; i < NUMTESTS; i++ ) {
  1126.         StartRecordTime( start );
  1127.         p_generic->CmpLT( bytedst, fsrc0, 0.0f, COUNT );
  1128.         StopRecordTime( end );
  1129.         GetBest( start, end, bestClocksGeneric );
  1130.     }
  1131.     PrintClocks( "generic->CmpLT( float[] >= float )", COUNT, bestClocksGeneric );
  1132.  
  1133.     bestClocksSIMD = 0;
  1134.     for ( i = 0; i < NUMTESTS; i++ ) {
  1135.         StartRecordTime( start );
  1136.         p_simd->CmpLT( bytedst2, fsrc0, 0.0f, COUNT );
  1137.         StopRecordTime( end );
  1138.         GetBest( start, end, bestClocksSIMD );
  1139.     }
  1140.  
  1141.     for ( i = 0; i < COUNT; i++ ) {
  1142.         if ( bytedst[i] != bytedst2[i] ) {
  1143.             break;
  1144.         }
  1145.     }
  1146.     result = ( i >= COUNT ) ? "ok" : S_COLOR_RED"X";
  1147.     PrintClocks( va( "   simd->CmpLT( float[] >= float ) %s", result ), COUNT, bestClocksSIMD, bestClocksGeneric );
  1148.  
  1149.     bestClocksGeneric = 0;
  1150.     for ( i = 0; i < NUMTESTS; i++ ) {
  1151.         memset( bytedst, 0, COUNT );
  1152.         StartRecordTime( start );
  1153.         p_generic->CmpLT( bytedst, 2, fsrc0, 0.0f, COUNT );
  1154.         StopRecordTime( end );
  1155.         GetBest( start, end, bestClocksGeneric );
  1156.     }
  1157.     PrintClocks( "generic->CmpLT( 2, float[] >= float )", COUNT, bestClocksGeneric );
  1158.  
  1159.     bestClocksSIMD = 0;
  1160.     for ( i = 0; i < NUMTESTS; i++ ) {
  1161.         memset( bytedst2, 0, COUNT );
  1162.         StartRecordTime( start );
  1163.         p_simd->CmpLT( bytedst2, 2, fsrc0, 0.0f, COUNT );
  1164.         StopRecordTime( end );
  1165.         GetBest( start, end, bestClocksSIMD );
  1166.     }
  1167.  
  1168.     for ( i = 0; i < COUNT; i++ ) {
  1169.         if ( bytedst[i] != bytedst2[i] ) {
  1170.             break;
  1171.         }
  1172.     }
  1173.     result = ( i >= COUNT ) ? "ok" : S_COLOR_RED"X";
  1174.     PrintClocks( va( "   simd->CmpLT( 2, float[] >= float ) %s", result ), COUNT, bestClocksSIMD, bestClocksGeneric );
  1175.  
  1176.     // ======================
  1177.  
  1178.     bestClocksGeneric = 0;
  1179.     for ( i = 0; i < NUMTESTS; i++ ) {
  1180.         StartRecordTime( start );
  1181.         p_generic->CmpLE( bytedst, fsrc0, 0.0f, COUNT );
  1182.         StopRecordTime( end );
  1183.         GetBest( start, end, bestClocksGeneric );
  1184.     }
  1185.     PrintClocks( "generic->CmpLE( float[] >= float )", COUNT, bestClocksGeneric );
  1186.  
  1187.     bestClocksSIMD = 0;
  1188.     for ( i = 0; i < NUMTESTS; i++ ) {
  1189.         StartRecordTime( start );
  1190.         p_simd->CmpLE( bytedst2, fsrc0, 0.0f, COUNT );
  1191.         StopRecordTime( end );
  1192.         GetBest( start, end, bestClocksSIMD );
  1193.     }
  1194.  
  1195.     for ( i = 0; i < COUNT; i++ ) {
  1196.         if ( bytedst[i] != bytedst2[i] ) {
  1197.             break;
  1198.         }
  1199.     }
  1200.     result = ( i >= COUNT ) ? "ok" : S_COLOR_RED"X";
  1201.     PrintClocks( va( "   simd->CmpLE( float[] >= float ) %s", result ), COUNT, bestClocksSIMD, bestClocksGeneric );
  1202.  
  1203.     bestClocksGeneric = 0;
  1204.     for ( i = 0; i < NUMTESTS; i++ ) {
  1205.         memset( bytedst, 0, COUNT );
  1206.         StartRecordTime( start );
  1207.         p_generic->CmpLE( bytedst, 2, fsrc0, 0.0f, COUNT );
  1208.         StopRecordTime( end );
  1209.         GetBest( start, end, bestClocksGeneric );
  1210.     }
  1211.     PrintClocks( "generic->CmpLE( 2, float[] >= float )", COUNT, bestClocksGeneric );
  1212.  
  1213.     bestClocksSIMD = 0;
  1214.     for ( i = 0; i < NUMTESTS; i++ ) {
  1215.         memset( bytedst2, 0, COUNT );
  1216.         StartRecordTime( start );
  1217.         p_simd->CmpLE( bytedst2, 2, fsrc0, 0.0f, COUNT );
  1218.         StopRecordTime( end );
  1219.         GetBest( start, end, bestClocksSIMD );
  1220.     }
  1221.  
  1222.     for ( i = 0; i < COUNT; i++ ) {
  1223.         if ( bytedst[i] != bytedst2[i] ) {
  1224.             break;
  1225.         }
  1226.     }
  1227.     result = ( i >= COUNT ) ? "ok" : S_COLOR_RED"X";
  1228.     PrintClocks( va( "   simd->CmpLE( 2, float[] >= float ) %s", result ), COUNT, bestClocksSIMD, bestClocksGeneric );
  1229. }
  1230.  
  1231. /*
  1232. ============
  1233. TestMinMax
  1234. ============
  1235. */
  1236. void TestMinMax( void ) {
  1237.     int i;
  1238.     TIME_TYPE start, end, bestClocksGeneric, bestClocksSIMD;
  1239.     ALIGN16( float fsrc0[COUNT]; )
  1240.     ALIGN16( idVec2 v2src0[COUNT]; )
  1241.     ALIGN16( idVec3 v3src0[COUNT]; )
  1242.     ALIGN16( idDrawVert drawVerts[COUNT]; )
  1243.     ALIGN16( int indexes[COUNT]; )
  1244.     float min = 0.0f, max = 0.0f, min2 = 0.0f, max2 = 0.0f;
  1245.     idVec2 v2min, v2max, v2min2, v2max2;
  1246.     idVec3 vmin, vmax, vmin2, vmax2;
  1247.     const char *result;
  1248.  
  1249.     idRandom srnd( RANDOM_SEED );
  1250.  
  1251.     for ( i = 0; i < COUNT; i++ ) {
  1252.         fsrc0[i] = srnd.CRandomFloat() * 10.0f;
  1253.         v2src0[i][0] = srnd.CRandomFloat() * 10.0f;
  1254.         v2src0[i][1] = srnd.CRandomFloat() * 10.0f;
  1255.         v3src0[i][0] = srnd.CRandomFloat() * 10.0f;
  1256.         v3src0[i][1] = srnd.CRandomFloat() * 10.0f;
  1257.         v3src0[i][2] = srnd.CRandomFloat() * 10.0f;
  1258.         drawVerts[i].xyz = v3src0[i];
  1259.         indexes[i] = i;
  1260.     }
  1261.  
  1262.     idLib::common->Printf("====================================\n" );
  1263.  
  1264.     bestClocksGeneric = 0;
  1265.     for ( i = 0; i < NUMTESTS; i++ ) {
  1266.         min = idMath::INFINITY;
  1267.         max = -idMath::INFINITY;
  1268.         StartRecordTime( start );
  1269.         p_generic->MinMax( min, max, fsrc0, COUNT );
  1270.         StopRecordTime( end );
  1271.         GetBest( start, end, bestClocksGeneric );
  1272.     }
  1273.     PrintClocks( "generic->MinMax( float[] )", COUNT, bestClocksGeneric );
  1274.  
  1275.     bestClocksSIMD = 0;
  1276.     for ( i = 0; i < NUMTESTS; i++ ) {
  1277.         StartRecordTime( start );
  1278.         p_simd->MinMax( min2, max2, fsrc0, COUNT );
  1279.         StopRecordTime( end );
  1280.         GetBest( start, end, bestClocksSIMD );
  1281.     }
  1282.  
  1283.     result = ( min == min2 && max == max2 ) ? "ok" : S_COLOR_RED"X";
  1284.     PrintClocks( va( "   simd->MinMax( float[] ) %s", result ), COUNT, bestClocksSIMD, bestClocksGeneric );
  1285.  
  1286.     bestClocksGeneric = 0;
  1287.     for ( i = 0; i < NUMTESTS; i++ ) {
  1288.         StartRecordTime( start );
  1289.         p_generic->MinMax( v2min, v2max, v2src0, COUNT );
  1290.         StopRecordTime( end );
  1291.         GetBest( start, end, bestClocksGeneric );
  1292.     }
  1293.     PrintClocks( "generic->MinMax( idVec2[] )", COUNT, bestClocksGeneric );
  1294.  
  1295.     bestClocksSIMD = 0;
  1296.     for ( i = 0; i < NUMTESTS; i++ ) {
  1297.         StartRecordTime( start );
  1298.         p_simd->MinMax( v2min2, v2max2, v2src0, COUNT );
  1299.         StopRecordTime( end );
  1300.         GetBest( start, end, bestClocksSIMD );
  1301.     }
  1302.  
  1303.     result = ( v2min == v2min2 && v2max == v2max2 ) ? "ok" : S_COLOR_RED"X";
  1304.     PrintClocks( va( "   simd->MinMax( idVec2[] ) %s", result ), COUNT, bestClocksSIMD, bestClocksGeneric );
  1305.  
  1306.     bestClocksGeneric = 0;
  1307.     for ( i = 0; i < NUMTESTS; i++ ) {
  1308.         StartRecordTime( start );
  1309.         p_generic->MinMax( vmin, vmax, v3src0, COUNT );
  1310.         StopRecordTime( end );
  1311.         GetBest( start, end, bestClocksGeneric );
  1312.     }
  1313.     PrintClocks( "generic->MinMax( idVec3[] )", COUNT, bestClocksGeneric );
  1314.  
  1315.     bestClocksSIMD = 0;
  1316.     for ( i = 0; i < NUMTESTS; i++ ) {
  1317.         StartRecordTime( start );
  1318.         p_simd->MinMax( vmin2, vmax2, v3src0, COUNT );
  1319.         StopRecordTime( end );
  1320.         GetBest( start, end, bestClocksSIMD );
  1321.     }
  1322.  
  1323.     result = ( vmin == vmin2 && vmax == vmax2 ) ? "ok" : S_COLOR_RED"X";
  1324.     PrintClocks( va( "   simd->MinMax( idVec3[] ) %s", result ), COUNT, bestClocksSIMD, bestClocksGeneric );
  1325.  
  1326.     bestClocksGeneric = 0;
  1327.     for ( i = 0; i < NUMTESTS; i++ ) {
  1328.         StartRecordTime( start );
  1329.         p_generic->MinMax( vmin, vmax, drawVerts, COUNT );
  1330.         StopRecordTime( end );
  1331.         GetBest( start, end, bestClocksGeneric );
  1332.     }
  1333.     PrintClocks( "generic->MinMax( idDrawVert[] )", COUNT, bestClocksGeneric );
  1334.  
  1335.     bestClocksSIMD = 0;
  1336.     for ( i = 0; i < NUMTESTS; i++ ) {
  1337.         StartRecordTime( start );
  1338.         p_simd->MinMax( vmin2, vmax2, drawVerts, COUNT );
  1339.         StopRecordTime( end );
  1340.         GetBest( start, end, bestClocksSIMD );
  1341.     }
  1342.  
  1343.     result = ( vmin == vmin2 && vmax == vmax2 ) ? "ok" : S_COLOR_RED"X";
  1344.     PrintClocks( va( "   simd->MinMax( idDrawVert[] ) %s", result ), COUNT, bestClocksSIMD, bestClocksGeneric );
  1345.  
  1346.     bestClocksGeneric = 0;
  1347.     for ( i = 0; i < NUMTESTS; i++ ) {
  1348.         StartRecordTime( start );
  1349.         p_generic->MinMax( vmin, vmax, drawVerts, indexes, COUNT );
  1350.         StopRecordTime( end );
  1351.         GetBest( start, end, bestClocksGeneric );
  1352.     }
  1353.     PrintClocks( "generic->MinMax( idDrawVert[], indexes[] )", COUNT, bestClocksGeneric );
  1354.  
  1355.     bestClocksSIMD = 0;
  1356.     for ( i = 0; i < NUMTESTS; i++ ) {
  1357.         StartRecordTime( start );
  1358.         p_simd->MinMax( vmin2, vmax2, drawVerts, indexes, COUNT );
  1359.         StopRecordTime( end );
  1360.         GetBest( start, end, bestClocksSIMD );
  1361.     }
  1362.  
  1363.     result = ( vmin == vmin2 && vmax == vmax2 ) ? "ok" : S_COLOR_RED"X";
  1364.     PrintClocks( va( "   simd->MinMax( idDrawVert[], indexes[] ) %s", result ), COUNT, bestClocksSIMD, bestClocksGeneric );
  1365. }
  1366.  
  1367. /*
  1368. ============
  1369. TestClamp
  1370. ============
  1371. */
  1372. void TestClamp( void ) {
  1373.     int i;
  1374.     TIME_TYPE start, end, bestClocksGeneric, bestClocksSIMD;
  1375.     ALIGN16( float fdst0[COUNT]; )
  1376.     ALIGN16( float fdst1[COUNT]; )
  1377.     ALIGN16( float fsrc0[COUNT]; )
  1378.     const char *result;
  1379.  
  1380.     idRandom srnd( RANDOM_SEED );
  1381.  
  1382.     for ( i = 0; i < COUNT; i++ ) {
  1383.         fsrc0[i] = srnd.CRandomFloat() * 10.0f;
  1384.     }
  1385.  
  1386.     idLib::common->Printf("====================================\n" );
  1387.  
  1388.     bestClocksGeneric = 0;
  1389.     for ( i = 0; i < NUMTESTS; i++ ) {
  1390.         StartRecordTime( start );
  1391.         p_generic->Clamp( fdst0, fsrc0, -1.0f, 1.0f, COUNT );
  1392.         StopRecordTime( end );
  1393.         GetBest( start, end, bestClocksGeneric );
  1394.     }
  1395.     PrintClocks( "generic->Clamp( float[] )", COUNT, bestClocksGeneric );
  1396.  
  1397.     bestClocksSIMD = 0;
  1398.     for ( i = 0; i < NUMTESTS; i++ ) {
  1399.         StartRecordTime( start );
  1400.         p_simd->Clamp( fdst1, fsrc0, -1.0f, 1.0f, COUNT );
  1401.         StopRecordTime( end );
  1402.         GetBest( start, end, bestClocksSIMD );
  1403.     }
  1404.  
  1405.     for ( i = 0; i < COUNT; i++ ) {
  1406.         if ( fdst0[i] != fdst1[i] ) {
  1407.             break;
  1408.         }
  1409.     }
  1410.     result = ( i >= COUNT ) ? "ok" : S_COLOR_RED"X";
  1411.     PrintClocks( va( "   simd->Clamp( float[] ) %s", result ), COUNT, bestClocksSIMD, bestClocksGeneric );
  1412.  
  1413.  
  1414.     bestClocksGeneric = 0;
  1415.     for ( i = 0; i < NUMTESTS; i++ ) {
  1416.         StartRecordTime( start );
  1417.         p_generic->ClampMin( fdst0, fsrc0, -1.0f, COUNT );
  1418.         StopRecordTime( end );
  1419.         GetBest( start, end, bestClocksGeneric );
  1420.     }
  1421.     PrintClocks( "generic->ClampMin( float[] )", COUNT, bestClocksGeneric );
  1422.  
  1423.     bestClocksSIMD = 0;
  1424.     for ( i = 0; i < NUMTESTS; i++ ) {
  1425.         StartRecordTime( start );
  1426.         p_simd->ClampMin( fdst1, fsrc0, -1.0f, COUNT );
  1427.         StopRecordTime( end );
  1428.         GetBest( start, end, bestClocksSIMD );
  1429.     }
  1430.  
  1431.     for ( i = 0; i < COUNT; i++ ) {
  1432.         if ( fdst0[i] != fdst1[i] ) {
  1433.             break;
  1434.         }
  1435.     }
  1436.     result = ( i >= COUNT ) ? "ok" : S_COLOR_RED"X";
  1437.     PrintClocks( va( "   simd->ClampMin( float[] ) %s", result ), COUNT, bestClocksSIMD, bestClocksGeneric );
  1438.  
  1439.  
  1440.     bestClocksGeneric = 0;
  1441.     for ( i = 0; i < NUMTESTS; i++ ) {
  1442.         StartRecordTime( start );
  1443.         p_generic->ClampMax( fdst0, fsrc0, 1.0f, COUNT );
  1444.         StopRecordTime( end );
  1445.         GetBest( start, end, bestClocksGeneric );
  1446.     }
  1447.     PrintClocks( "generic->ClampMax( float[] )", COUNT, bestClocksGeneric );
  1448.  
  1449.     bestClocksSIMD = 0;
  1450.     for ( i = 0; i < NUMTESTS; i++ ) {
  1451.         StartRecordTime( start );
  1452.         p_simd->ClampMax( fdst1, fsrc0, 1.0f, COUNT );
  1453.         StopRecordTime( end );
  1454.         GetBest( start, end, bestClocksSIMD );
  1455.     }
  1456.  
  1457.     for ( i = 0; i < COUNT; i++ ) {
  1458.         if ( fdst0[i] != fdst1[i] ) {
  1459.             break;
  1460.         }
  1461.     }
  1462.     result = ( i >= COUNT ) ? "ok" : S_COLOR_RED"X";
  1463.     PrintClocks( va( "   simd->ClampMax( float[] ) %s", result ), COUNT, bestClocksSIMD, bestClocksGeneric );
  1464. }
  1465.  
  1466. /*
  1467. ============
  1468. TestMemcpy
  1469. ============
  1470. */
  1471. void TestMemcpy( void ) {
  1472.     int i, j;
  1473.     byte test0[8192];
  1474.     byte test1[8192];
  1475.  
  1476.     idRandom random( RANDOM_SEED );
  1477.  
  1478.     idLib::common->Printf("====================================\n" );
  1479.  
  1480.     for ( i = 5; i < 8192; i += 31 ) {
  1481.         for ( j = 0; j < i; j++ ) {
  1482.             test0[j] = random.RandomInt( 255 );
  1483.         }
  1484.         p_simd->Memcpy( test1, test0, 8192 );
  1485.         for ( j = 0; j < i; j++ ) {
  1486.             if ( test1[j] != test0[j] ) {
  1487.                 idLib::common->Printf( "   simd->Memcpy() "S_COLOR_RED"X\n" );
  1488.                 return;
  1489.             }
  1490.         }
  1491.     }
  1492.     idLib::common->Printf( "   simd->Memcpy() ok\n" );
  1493. }
  1494.  
  1495. /*
  1496. ============
  1497. TestMemset
  1498. ============
  1499. */
  1500. void TestMemset( void ) {
  1501.     int i, j, k;
  1502.     byte test[8192];
  1503.  
  1504.     for ( i = 0; i < 8192; i++ ) {
  1505.         test[i] = 0;
  1506.     }
  1507.  
  1508.     for ( i = 5; i < 8192; i += 31 ) {
  1509.         for ( j = -1; j <= 1; j++ ) {
  1510.             p_simd->Memset( test, j, i );
  1511.             for ( k = 0; k < i; k++ ) {
  1512.                 if ( test[k] != (byte)j ) {
  1513.                     idLib::common->Printf( "   simd->Memset() "S_COLOR_RED"X\n" );
  1514.                     return;
  1515.                 }
  1516.             }
  1517.         }
  1518.     }
  1519.     idLib::common->Printf( "   simd->Memset() ok\n" );
  1520. }
  1521.  
  1522. #define    MATX_SIMD_EPSILON            1e-5f
  1523.  
  1524. /*
  1525. ============
  1526. TestMatXMultiplyVecX
  1527. ============
  1528. */
  1529. void TestMatXMultiplyVecX( void ) {
  1530.     int i, j;
  1531.     TIME_TYPE start, end, bestClocksGeneric, bestClocksSIMD;
  1532.     const char *result;
  1533.     idMatX mat;
  1534.     idVecX src(6);
  1535.     idVecX dst(6);
  1536.     idVecX tst(6);
  1537.  
  1538.     src[0] = 1.0f;
  1539.     src[1] = 2.0f;
  1540.     src[2] = 3.0f;
  1541.     src[3] = 4.0f;
  1542.     src[4] = 5.0f;
  1543.     src[5] = 6.0f;
  1544.  
  1545.     idLib::common->Printf("================= NxN * Nx1 ===================\n" );
  1546.  
  1547.     for ( i = 1; i <= 6; i++ ) {
  1548.         mat.Random( i, i, RANDOM_SEED, -10.0f, 10.0f );
  1549.  
  1550.         bestClocksGeneric = 0;
  1551.         for ( j = 0; j < NUMTESTS; j++ ) {
  1552.             dst.Zero();
  1553.             StartRecordTime( start );
  1554.             p_generic->MatX_MultiplyVecX( dst, mat, src );
  1555.             StopRecordTime( end );
  1556.             GetBest( start, end, bestClocksGeneric );
  1557.         }
  1558.         tst = dst;
  1559.  
  1560.         PrintClocks( va( "generic->MatX_MultiplyVecX %dx%d*%dx1", i, i, i ), 1, bestClocksGeneric );
  1561.  
  1562.         bestClocksSIMD = 0;
  1563.         for ( j = 0; j < NUMTESTS; j++ ) {
  1564.             dst.Zero();
  1565.             StartRecordTime( start );
  1566.             p_simd->MatX_MultiplyVecX( dst, mat, src );
  1567.             StopRecordTime( end );
  1568.             GetBest( start, end, bestClocksSIMD );
  1569.         }
  1570.  
  1571.         result = dst.Compare( tst, MATX_SIMD_EPSILON ) ? "ok" : S_COLOR_RED"X";
  1572.         PrintClocks( va( "   simd->MatX_MultiplyVecX %dx%d*%dx1 %s", i, i, i, result ), 1, bestClocksSIMD, bestClocksGeneric );
  1573.     }
  1574.  
  1575.     idLib::common->Printf("================= Nx6 * 6x1 ===================\n" );
  1576.  
  1577.     for ( i = 1; i <= 6; i++ ) {
  1578.         mat.Random( i, 6, RANDOM_SEED, -10.0f, 10.0f );
  1579.  
  1580.         bestClocksGeneric = 0;
  1581.         for ( j = 0; j < NUMTESTS; j++ ) {
  1582.             dst.Zero();
  1583.             StartRecordTime( start );
  1584.             p_generic->MatX_MultiplyVecX( dst, mat, src );
  1585.             StopRecordTime( end );
  1586.             GetBest( start, end, bestClocksGeneric );
  1587.         }
  1588.         tst = dst;
  1589.  
  1590.         PrintClocks( va( "generic->MatX_MultiplyVecX %dx6*6x1", i ), 1, bestClocksGeneric );
  1591.  
  1592.         bestClocksSIMD = 0;
  1593.         for ( j = 0; j < NUMTESTS; j++ ) {
  1594.             dst.Zero();
  1595.             StartRecordTime( start );
  1596.             p_simd->MatX_MultiplyVecX( dst, mat, src );
  1597.             StopRecordTime( end );
  1598.             GetBest( start, end, bestClocksSIMD );
  1599.         }
  1600.  
  1601.         result = dst.Compare( tst, MATX_SIMD_EPSILON ) ? "ok" : S_COLOR_RED"X";
  1602.         PrintClocks( va( "   simd->MatX_MultiplyVecX %dx6*6x1 %s", i, result ), 1, bestClocksSIMD, bestClocksGeneric );
  1603.     }
  1604.  
  1605.     idLib::common->Printf("================= 6xN * Nx1 ===================\n" );
  1606.  
  1607.     for ( i = 1; i <= 6; i++ ) {
  1608.         mat.Random( 6, i, RANDOM_SEED, -10.0f, 10.0f );
  1609.  
  1610.         bestClocksGeneric = 0;
  1611.         for ( j = 0; j < NUMTESTS; j++ ) {
  1612.             dst.Zero();
  1613.             StartRecordTime( start );
  1614.             p_generic->MatX_MultiplyVecX( dst, mat, src );
  1615.             StopRecordTime( end );
  1616.             GetBest( start, end, bestClocksGeneric );
  1617.         }
  1618.         tst = dst;
  1619.  
  1620.         PrintClocks( va( "generic->MatX_MultiplyVecX 6x%d*%dx1", i, i ), 1, bestClocksGeneric );
  1621.  
  1622.         bestClocksSIMD = 0;
  1623.         for ( j = 0; j < NUMTESTS; j++ ) {
  1624.             StartRecordTime( start );
  1625.             p_simd->MatX_MultiplyVecX( dst, mat, src );
  1626.             StopRecordTime( end );
  1627.             GetBest( start, end, bestClocksSIMD );
  1628.         }
  1629.  
  1630.         result = dst.Compare( tst, MATX_SIMD_EPSILON ) ? "ok" : S_COLOR_RED"X";
  1631.         PrintClocks( va( "   simd->MatX_MultiplyVecX 6x%d*%dx1 %s", i, i, result ), 1, bestClocksSIMD, bestClocksGeneric );
  1632.     }
  1633. }
  1634.  
  1635. /*
  1636. ============
  1637. TestMatXMultiplyAddVecX
  1638. ============
  1639. */
  1640. void TestMatXMultiplyAddVecX( void ) {
  1641.     int i, j;
  1642.     TIME_TYPE start, end, bestClocksGeneric, bestClocksSIMD;
  1643.     const char *result;
  1644.     idMatX mat;
  1645.     idVecX src(6);
  1646.     idVecX dst(6);
  1647.     idVecX tst(6);
  1648.  
  1649.     src[0] = 1.0f;
  1650.     src[1] = 2.0f;
  1651.     src[2] = 3.0f;
  1652.     src[3] = 4.0f;
  1653.     src[4] = 5.0f;
  1654.     src[5] = 6.0f;
  1655.  
  1656.     idLib::common->Printf("================= NxN * Nx1 ===================\n" );
  1657.  
  1658.     for ( i = 1; i <= 6; i++ ) {
  1659.         mat.Random( i, i, RANDOM_SEED, -10.0f, 10.0f );
  1660.  
  1661.         bestClocksGeneric = 0;
  1662.         for ( j = 0; j < NUMTESTS; j++ ) {
  1663.             dst.Zero();
  1664.             StartRecordTime( start );
  1665.             p_generic->MatX_MultiplyAddVecX( dst, mat, src );
  1666.             StopRecordTime( end );
  1667.             GetBest( start, end, bestClocksGeneric );
  1668.         }
  1669.         tst = dst;
  1670.  
  1671.         PrintClocks( va( "generic->MatX_MultiplyAddVecX %dx%d*%dx1", i, i, i ), 1, bestClocksGeneric );
  1672.  
  1673.         bestClocksSIMD = 0;
  1674.         for ( j = 0; j < NUMTESTS; j++ ) {
  1675.             dst.Zero();
  1676.             StartRecordTime( start );
  1677.             p_simd->MatX_MultiplyAddVecX( dst, mat, src );
  1678.             StopRecordTime( end );
  1679.             GetBest( start, end, bestClocksSIMD );
  1680.         }
  1681.  
  1682.         result = dst.Compare( tst, MATX_SIMD_EPSILON ) ? "ok" : S_COLOR_RED"X";
  1683.         PrintClocks( va( "   simd->MatX_MultiplyAddVecX %dx%d*%dx1 %s", i, i, i, result ), 1, bestClocksSIMD, bestClocksGeneric );
  1684.     }
  1685.  
  1686.     idLib::common->Printf("================= Nx6 * 6x1 ===================\n" );
  1687.  
  1688.     for ( i = 1; i <= 6; i++ ) {
  1689.         mat.Random( i, 6, RANDOM_SEED, -10.0f, 10.0f );
  1690.  
  1691.         bestClocksGeneric = 0;
  1692.         for ( j = 0; j < NUMTESTS; j++ ) {
  1693.             dst.Zero();
  1694.             StartRecordTime( start );
  1695.             p_generic->MatX_MultiplyAddVecX( dst, mat, src );
  1696.             StopRecordTime( end );
  1697.             GetBest( start, end, bestClocksGeneric );
  1698.         }
  1699.         tst = dst;
  1700.  
  1701.         PrintClocks( va( "generic->MatX_MultiplyAddVecX %dx6*6x1", i ), 1, bestClocksGeneric );
  1702.  
  1703.         bestClocksSIMD = 0;
  1704.         for ( j = 0; j < NUMTESTS; j++ ) {
  1705.             dst.Zero();
  1706.             StartRecordTime( start );
  1707.             p_simd->MatX_MultiplyAddVecX( dst, mat, src );
  1708.             StopRecordTime( end );
  1709.             GetBest( start, end, bestClocksSIMD );
  1710.         }
  1711.  
  1712.         result = dst.Compare( tst, MATX_SIMD_EPSILON ) ? "ok" : S_COLOR_RED"X";
  1713.         PrintClocks( va( "   simd->MatX_MultiplyAddVecX %dx6*6x1 %s", i, result ), 1, bestClocksSIMD, bestClocksGeneric );
  1714.     }
  1715.  
  1716.     idLib::common->Printf("================= 6xN * Nx1 ===================\n" );
  1717.  
  1718.     for ( i = 1; i <= 6; i++ ) {
  1719.         mat.Random( 6, i, RANDOM_SEED, -10.0f, 10.0f );
  1720.  
  1721.         bestClocksGeneric = 0;
  1722.         for ( j = 0; j < NUMTESTS; j++ ) {
  1723.             dst.Zero();
  1724.             StartRecordTime( start );
  1725.             p_generic->MatX_MultiplyAddVecX( dst, mat, src );
  1726.             StopRecordTime( end );
  1727.             GetBest( start, end, bestClocksGeneric );
  1728.         }
  1729.         tst = dst;
  1730.  
  1731.         PrintClocks( va( "generic->MatX_MultiplyAddVecX 6x%d*%dx1", i, i ), 1, bestClocksGeneric );
  1732.  
  1733.         bestClocksSIMD = 0;
  1734.         for ( j = 0; j < NUMTESTS; j++ ) {
  1735.             dst.Zero();
  1736.             StartRecordTime( start );
  1737.             p_simd->MatX_MultiplyAddVecX( dst, mat, src );
  1738.             StopRecordTime( end );
  1739.             GetBest( start, end, bestClocksSIMD );
  1740.         }
  1741.  
  1742.         result = dst.Compare( tst, MATX_SIMD_EPSILON ) ? "ok" : S_COLOR_RED"X";
  1743.         PrintClocks( va( "   simd->MatX_MultiplyAddVecX 6x%d*%dx1 %s", i, i, result ), 1, bestClocksSIMD, bestClocksGeneric );
  1744.     }
  1745. }
  1746.  
  1747. /*
  1748. ============
  1749. TestMatXTransposeMultiplyVecX
  1750. ============
  1751. */
  1752. void TestMatXTransposeMultiplyVecX( void ) {
  1753.     int i, j;
  1754.     TIME_TYPE start, end, bestClocksGeneric, bestClocksSIMD;
  1755.     const char *result;
  1756.     idMatX mat;
  1757.     idVecX src(6);
  1758.     idVecX dst(6);
  1759.     idVecX tst(6);
  1760.  
  1761.     src[0] = 1.0f;
  1762.     src[1] = 2.0f;
  1763.     src[2] = 3.0f;
  1764.     src[3] = 4.0f;
  1765.     src[4] = 5.0f;
  1766.     src[5] = 6.0f;
  1767.  
  1768.     idLib::common->Printf("================= Nx6 * Nx1 ===================\n" );
  1769.  
  1770.     for ( i = 1; i <= 6; i++ ) {
  1771.         mat.Random( i, 6, RANDOM_SEED, -10.0f, 10.0f );
  1772.  
  1773.         bestClocksGeneric = 0;
  1774.         for ( j = 0; j < NUMTESTS; j++ ) {
  1775.             dst.Zero();
  1776.             StartRecordTime( start );
  1777.             p_generic->MatX_TransposeMultiplyVecX( dst, mat, src );
  1778.             StopRecordTime( end );
  1779.             GetBest( start, end, bestClocksGeneric );
  1780.         }
  1781.         tst = dst;
  1782.  
  1783.         PrintClocks( va( "generic->MatX_TransposeMulVecX %dx6*%dx1", i, i ), 1, bestClocksGeneric );
  1784.  
  1785.         bestClocksSIMD = 0;
  1786.         for ( j = 0; j < NUMTESTS; j++ ) {
  1787.             dst.Zero();
  1788.             StartRecordTime( start );
  1789.             p_simd->MatX_TransposeMultiplyVecX( dst, mat, src );
  1790.             StopRecordTime( end );
  1791.             GetBest( start, end, bestClocksSIMD );
  1792.         }
  1793.  
  1794.         result = dst.Compare( tst, MATX_SIMD_EPSILON ) ? "ok" : S_COLOR_RED"X";
  1795.         PrintClocks( va( "   simd->MatX_TransposeMulVecX %dx6*%dx1 %s", i, i, result ), 1, bestClocksSIMD, bestClocksGeneric );
  1796.     }
  1797.  
  1798.     idLib::common->Printf("================= 6xN * 6x1 ===================\n" );
  1799.  
  1800.     for ( i = 1; i <= 6; i++ ) {
  1801.         mat.Random( 6, i, RANDOM_SEED, -10.0f, 10.0f );
  1802.  
  1803.         bestClocksGeneric = 0;
  1804.         for ( j = 0; j < NUMTESTS; j++ ) {
  1805.             dst.Zero();
  1806.             StartRecordTime( start );
  1807.             p_generic->MatX_TransposeMultiplyVecX( dst, mat, src );
  1808.             StopRecordTime( end );
  1809.             GetBest( start, end, bestClocksGeneric );
  1810.         }
  1811.         tst = dst;
  1812.  
  1813.         PrintClocks( va( "generic->MatX_TransposeMulVecX 6x%d*6x1", i ), 1, bestClocksGeneric );
  1814.  
  1815.         bestClocksSIMD = 0;
  1816.         for ( j = 0; j < NUMTESTS; j++ ) {
  1817.             dst.Zero();
  1818.             StartRecordTime( start );
  1819.             p_simd->MatX_TransposeMultiplyVecX( dst, mat, src );
  1820.             StopRecordTime( end );
  1821.             GetBest( start, end, bestClocksSIMD );
  1822.         }
  1823.  
  1824.         result = dst.Compare( tst, MATX_SIMD_EPSILON ) ? "ok" : S_COLOR_RED"X";
  1825.         PrintClocks( va( "   simd->MatX_TransposeMulVecX 6x%d*6x1 %s", i, result ), 1, bestClocksSIMD, bestClocksGeneric );
  1826.     }
  1827. }
  1828.  
  1829. /*
  1830. ============
  1831. TestMatXTransposeMultiplyAddVecX
  1832. ============
  1833. */
  1834. void TestMatXTransposeMultiplyAddVecX( void ) {
  1835.     int i, j;
  1836.     TIME_TYPE start, end, bestClocksGeneric, bestClocksSIMD;
  1837.     const char *result;
  1838.     idMatX mat;
  1839.     idVecX src(6);
  1840.     idVecX dst(6);
  1841.     idVecX tst(6);
  1842.  
  1843.     src[0] = 1.0f;
  1844.     src[1] = 2.0f;
  1845.     src[2] = 3.0f;
  1846.     src[3] = 4.0f;
  1847.     src[4] = 5.0f;
  1848.     src[5] = 6.0f;
  1849.  
  1850.     idLib::common->Printf("================= Nx6 * Nx1 ===================\n" );
  1851.  
  1852.     for ( i = 1; i <= 6; i++ ) {
  1853.         mat.Random( i, 6, RANDOM_SEED, -10.0f, 10.0f );
  1854.  
  1855.         bestClocksGeneric = 0;
  1856.         for ( j = 0; j < NUMTESTS; j++ ) {
  1857.             dst.Zero();
  1858.             StartRecordTime( start );
  1859.             p_generic->MatX_TransposeMultiplyAddVecX( dst, mat, src );
  1860.             StopRecordTime( end );
  1861.             GetBest( start, end, bestClocksGeneric );
  1862.         }
  1863.         tst = dst;
  1864.  
  1865.         PrintClocks( va( "generic->MatX_TransposeMulAddVecX %dx6*%dx1", i, i ), 1, bestClocksGeneric );
  1866.  
  1867.         bestClocksSIMD = 0;
  1868.         for ( j = 0; j < NUMTESTS; j++ ) {
  1869.             dst.Zero();
  1870.             StartRecordTime( start );
  1871.             p_simd->MatX_TransposeMultiplyAddVecX( dst, mat, src );
  1872.             StopRecordTime( end );
  1873.             GetBest( start, end, bestClocksSIMD );
  1874.         }
  1875.  
  1876.         result = dst.Compare( tst, MATX_SIMD_EPSILON ) ? "ok" : S_COLOR_RED"X";
  1877.         PrintClocks( va( "   simd->MatX_TransposeMulAddVecX %dx6*%dx1 %s", i, i, result ), 1, bestClocksSIMD, bestClocksGeneric );
  1878.     }
  1879.  
  1880.     idLib::common->Printf("================= 6xN * 6x1 ===================\n" );
  1881.  
  1882.     for ( i = 1; i <= 6; i++ ) {
  1883.         mat.Random( 6, i, RANDOM_SEED, -10.0f, 10.0f );
  1884.  
  1885.         bestClocksGeneric = 0;
  1886.         for ( j = 0; j < NUMTESTS; j++ ) {
  1887.             dst.Zero();
  1888.             StartRecordTime( start );
  1889.             p_generic->MatX_TransposeMultiplyAddVecX( dst, mat, src );
  1890.             StopRecordTime( end );
  1891.             GetBest( start, end, bestClocksGeneric );
  1892.         }
  1893.         tst = dst;
  1894.  
  1895.         PrintClocks( va( "generic->MatX_TransposeMulAddVecX 6x%d*6x1", i ), 1, bestClocksGeneric );
  1896.  
  1897.         bestClocksSIMD = 0;
  1898.         for ( j = 0; j < NUMTESTS; j++ ) {
  1899.             dst.Zero();
  1900.             StartRecordTime( start );
  1901.             p_simd->MatX_TransposeMultiplyAddVecX( dst, mat, src );
  1902.             StopRecordTime( end );
  1903.             GetBest( start, end, bestClocksSIMD );
  1904.         }
  1905.  
  1906.         result = dst.Compare( tst, MATX_SIMD_EPSILON ) ? "ok" : S_COLOR_RED"X";
  1907.         PrintClocks( va( "   simd->MatX_TransposeMulAddVecX 6x%d*6x1 %s", i, result ), 1, bestClocksSIMD, bestClocksGeneric );
  1908.     }
  1909. }
  1910.  
  1911. /*
  1912. ============
  1913. TestMatXMultiplyMatX
  1914. ============
  1915. */
  1916. #define TEST_VALUE_RANGE            10.0f
  1917. #define    MATX_MATX_SIMD_EPSILON        1e-4f
  1918.  
  1919. void TestMatXMultiplyMatX( void ) {
  1920.     int i, j;
  1921.     TIME_TYPE start, end, bestClocksGeneric, bestClocksSIMD;
  1922.     const char *result;
  1923.     idMatX m1, m2, dst, tst;
  1924.  
  1925.     idLib::common->Printf("================= NxN * Nx6 ===================\n" );
  1926.  
  1927.     // NxN * Nx6
  1928.     for ( i = 1; i <= 5; i++ ) {
  1929.         m1.Random( i, i, RANDOM_SEED, -TEST_VALUE_RANGE, TEST_VALUE_RANGE );
  1930.         m2.Random( i, 6, RANDOM_SEED, -TEST_VALUE_RANGE, TEST_VALUE_RANGE );
  1931.         dst.SetSize( i, 6 );
  1932.  
  1933.         bestClocksGeneric = 0;
  1934.         for ( j = 0; j < NUMTESTS; j++ ) {
  1935.             StartRecordTime( start );
  1936.             p_generic->MatX_MultiplyMatX( dst, m1, m2 );
  1937.             StopRecordTime( end );
  1938.             GetBest( start, end, bestClocksGeneric );
  1939.         }
  1940.         tst = dst;
  1941.  
  1942.         PrintClocks( va( "generic->MatX_MultiplyMatX %dx%d*%dx6", i, i, i ), 1, bestClocksGeneric );
  1943.  
  1944.         bestClocksSIMD = 0;
  1945.         for ( j = 0; j < NUMTESTS; j++ ) {
  1946.             StartRecordTime( start );
  1947.             p_simd->MatX_MultiplyMatX( dst, m1, m2 );
  1948.             StopRecordTime( end );
  1949.             GetBest( start, end, bestClocksSIMD );
  1950.         }
  1951.  
  1952.         result = dst.Compare( tst, MATX_MATX_SIMD_EPSILON ) ? "ok" : S_COLOR_RED"X";
  1953.         PrintClocks( va( "   simd->MatX_MultiplyMatX %dx%d*%dx6 %s", i, i, i, result ), 1, bestClocksSIMD, bestClocksGeneric );
  1954.     }
  1955.  
  1956.     idLib::common->Printf("================= 6xN * Nx6 ===================\n" );
  1957.  
  1958.     // 6xN * Nx6
  1959.     for ( i = 1; i <= 5; i++ ) {
  1960.         m1.Random( 6, i, RANDOM_SEED, -TEST_VALUE_RANGE, TEST_VALUE_RANGE );
  1961.         m2.Random( i, 6, RANDOM_SEED, -TEST_VALUE_RANGE, TEST_VALUE_RANGE );
  1962.         dst.SetSize( 6, 6 );
  1963.  
  1964.         bestClocksGeneric = 0;
  1965.         for ( j = 0; j < NUMTESTS; j++ ) {
  1966.             StartRecordTime( start );
  1967.             p_generic->MatX_MultiplyMatX( dst, m1, m2 );
  1968.             StopRecordTime( end );
  1969.             GetBest( start, end, bestClocksGeneric );
  1970.         }
  1971.         tst = dst;
  1972.  
  1973.         PrintClocks( va( "generic->MatX_MultiplyMatX 6x%d*%dx6", i, i ), 1, bestClocksGeneric );
  1974.  
  1975.         bestClocksSIMD = 0;
  1976.         for ( j = 0; j < NUMTESTS; j++ ) {
  1977.             StartRecordTime( start );
  1978.             p_simd->MatX_MultiplyMatX( dst, m1, m2 );
  1979.             StopRecordTime( end );
  1980.             GetBest( start, end, bestClocksSIMD );
  1981.         }
  1982.  
  1983.         result = dst.Compare( tst, MATX_MATX_SIMD_EPSILON ) ? "ok" : S_COLOR_RED"X";
  1984.         PrintClocks( va( "   simd->MatX_MultiplyMatX 6x%d*%dx6 %s", i, i, result ), 1, bestClocksSIMD, bestClocksGeneric );
  1985.     }
  1986.  
  1987.     idLib::common->Printf("================= Nx6 * 6xN ===================\n" );
  1988.  
  1989.     // Nx6 * 6xN
  1990.     for ( i = 1; i <= 5; i++ ) {
  1991.         m1.Random( i, 6, RANDOM_SEED, -TEST_VALUE_RANGE, TEST_VALUE_RANGE );
  1992.         m2.Random( 6, i, RANDOM_SEED, -TEST_VALUE_RANGE, TEST_VALUE_RANGE );
  1993.         dst.SetSize( i, i );
  1994.  
  1995.         bestClocksGeneric = 0;
  1996.         for ( j = 0; j < NUMTESTS; j++ ) {
  1997.             StartRecordTime( start );
  1998.             p_generic->MatX_MultiplyMatX( dst, m1, m2 );
  1999.             StopRecordTime( end );
  2000.             GetBest( start, end, bestClocksGeneric );
  2001.         }
  2002.         tst = dst;
  2003.  
  2004.         PrintClocks( va( "generic->MatX_MultiplyMatX %dx6*6x%d", i, i ), 1, bestClocksGeneric );
  2005.  
  2006.         bestClocksSIMD = 0;
  2007.         for ( j = 0; j < NUMTESTS; j++ ) {
  2008.             StartRecordTime( start );
  2009.             p_simd->MatX_MultiplyMatX( dst, m1, m2 );
  2010.             StopRecordTime( end );
  2011.             GetBest( start, end, bestClocksSIMD );
  2012.         }
  2013.  
  2014.         result = dst.Compare( tst, MATX_MATX_SIMD_EPSILON ) ? "ok" : S_COLOR_RED"X";
  2015.         PrintClocks( va( "   simd->MatX_MultiplyMatX %dx6*6x%d %s", i, i, result ), 1, bestClocksSIMD, bestClocksGeneric );
  2016.     }
  2017.  
  2018.     idLib::common->Printf("================= 6x6 * 6xN ===================\n" );
  2019.  
  2020.     // 6x6 * 6xN
  2021.     for ( i = 1; i <= 6; i++ ) {
  2022.         m1.Random( 6, 6, RANDOM_SEED, -TEST_VALUE_RANGE, TEST_VALUE_RANGE );
  2023.         m2.Random( 6, i, RANDOM_SEED, -TEST_VALUE_RANGE, TEST_VALUE_RANGE );
  2024.         dst.SetSize( 6, i );
  2025.  
  2026.         bestClocksGeneric = 0;
  2027.         for ( j = 0; j < NUMTESTS; j++ ) {
  2028.             StartRecordTime( start );
  2029.             p_generic->MatX_MultiplyMatX( dst, m1, m2 );
  2030.             StopRecordTime( end );
  2031.             GetBest( start, end, bestClocksGeneric );
  2032.         }
  2033.         tst = dst;
  2034.  
  2035.         PrintClocks( va( "generic->MatX_MultiplyMatX 6x6*6x%d", i ), 1, bestClocksGeneric );
  2036.  
  2037.         bestClocksSIMD = 0;
  2038.         for ( j = 0; j < NUMTESTS; j++ ) {
  2039.             StartRecordTime( start );
  2040.             p_simd->MatX_MultiplyMatX( dst, m1, m2 );
  2041.             StopRecordTime( end );
  2042.             GetBest( start, end, bestClocksSIMD );
  2043.         }
  2044.  
  2045.         result = dst.Compare( tst, MATX_MATX_SIMD_EPSILON ) ? "ok" : S_COLOR_RED"X";
  2046.         PrintClocks( va( "   simd->MatX_MultiplyMatX 6x6*6x%d %s", i, result ), 1, bestClocksSIMD, bestClocksGeneric );
  2047.     }
  2048. }
  2049.  
  2050. /*
  2051. ============
  2052. TestMatXTransposeMultiplyMatX
  2053. ============
  2054. */
  2055. void TestMatXTransposeMultiplyMatX( void ) {
  2056.     int i, j;
  2057.     TIME_TYPE start, end, bestClocksGeneric, bestClocksSIMD;
  2058.     const char *result;
  2059.     idMatX m1, m2, dst, tst;
  2060.  
  2061.     idLib::common->Printf("================= Nx6 * NxN ===================\n" );
  2062.  
  2063.     // Nx6 * NxN
  2064.     for ( i = 1; i <= 5; i++ ) {
  2065.         m1.Random( i, 6, RANDOM_SEED, -TEST_VALUE_RANGE, TEST_VALUE_RANGE );
  2066.         m2.Random( i, i, RANDOM_SEED, -TEST_VALUE_RANGE, TEST_VALUE_RANGE );
  2067.         dst.SetSize( 6, i );
  2068.  
  2069.         bestClocksGeneric = 0;
  2070.         for ( j = 0; j < NUMTESTS; j++ ) {
  2071.             StartRecordTime( start );
  2072.             p_generic->MatX_TransposeMultiplyMatX( dst, m1, m2 );
  2073.             StopRecordTime( end );
  2074.             GetBest( start, end, bestClocksGeneric );
  2075.         }
  2076.         tst = dst;
  2077.  
  2078.         PrintClocks( va( "generic->MatX_TransMultiplyMatX %dx6*%dx%d", i, i, i ), 1, bestClocksGeneric );
  2079.  
  2080.         bestClocksSIMD = 0;
  2081.         for ( j = 0; j < NUMTESTS; j++ ) {
  2082.             StartRecordTime( start );
  2083.             p_simd->MatX_TransposeMultiplyMatX( dst, m1, m2 );
  2084.             StopRecordTime( end );
  2085.             GetBest( start, end, bestClocksSIMD );
  2086.         }
  2087.  
  2088.         result = dst.Compare( tst, MATX_MATX_SIMD_EPSILON ) ? "ok" : S_COLOR_RED"X";
  2089.         PrintClocks( va( "   simd->MatX_TransMultiplyMatX %dx6*%dx%d %s", i, i, i, result ), 1, bestClocksSIMD, bestClocksGeneric );
  2090.     }
  2091.  
  2092.     idLib::common->Printf("================= 6xN * 6x6 ===================\n" );
  2093.  
  2094.     // 6xN * 6x6
  2095.     for ( i = 1; i <= 6; i++ ) {
  2096.         m1.Random( 6, i, RANDOM_SEED, -TEST_VALUE_RANGE, TEST_VALUE_RANGE );
  2097.         m2.Random( 6, 6, RANDOM_SEED, -TEST_VALUE_RANGE, TEST_VALUE_RANGE );
  2098.         dst.SetSize( i, 6 );
  2099.  
  2100.         bestClocksGeneric = 0;
  2101.         for ( j = 0; j < NUMTESTS; j++ ) {
  2102.             StartRecordTime( start );
  2103.             p_generic->MatX_TransposeMultiplyMatX( dst, m1, m2 );
  2104.             StopRecordTime( end );
  2105.             GetBest( start, end, bestClocksGeneric );
  2106.         }
  2107.         tst = dst;
  2108.  
  2109.         PrintClocks( va( "generic->MatX_TransMultiplyMatX 6x%d*6x6", i ), 1, bestClocksGeneric );
  2110.  
  2111.         bestClocksSIMD = 0;
  2112.         for ( j = 0; j < NUMTESTS; j++ ) {
  2113.             StartRecordTime( start );
  2114.             p_simd->MatX_TransposeMultiplyMatX( dst, m1, m2 );
  2115.             StopRecordTime( end );
  2116.             GetBest( start, end, bestClocksSIMD );
  2117.         }
  2118.  
  2119.         result = dst.Compare( tst, MATX_MATX_SIMD_EPSILON ) ? "ok" : S_COLOR_RED"X";
  2120.         PrintClocks( va( "   simd->MatX_TransMultiplyMatX 6x%d*6x6 %s", i, result ), 1, bestClocksSIMD, bestClocksGeneric );
  2121.     }
  2122. }
  2123.  
  2124. #define MATX_LTS_SIMD_EPSILON        1.0f
  2125. #define MATX_LTS_SOLVE_SIZE            100
  2126.  
  2127. /*
  2128. ============
  2129. TestMatXLowerTriangularSolve
  2130. ============
  2131. */
  2132. void TestMatXLowerTriangularSolve( void ) {
  2133.     int i, j;
  2134.     TIME_TYPE start, end, bestClocksGeneric, bestClocksSIMD;
  2135.     const char *result;
  2136.     idMatX L;
  2137.     idVecX x, b, tst;
  2138.  
  2139.     idLib::common->Printf("====================================\n" );
  2140.  
  2141.     L.Random( MATX_LTS_SOLVE_SIZE, MATX_LTS_SOLVE_SIZE, 0, -1.0f, 1.0f );
  2142.     x.SetSize( MATX_LTS_SOLVE_SIZE );
  2143.     b.Random( MATX_LTS_SOLVE_SIZE, 0, -1.0f, 1.0f );
  2144.  
  2145.     for ( i = 1; i < MATX_LTS_SOLVE_SIZE; i++ ) {
  2146.  
  2147.         x.Zero( i );
  2148.  
  2149.         bestClocksGeneric = 0;
  2150.         for ( j = 0; j < NUMTESTS; j++ ) {
  2151.             StartRecordTime( start );
  2152.             p_generic->MatX_LowerTriangularSolve( L, x.ToFloatPtr(), b.ToFloatPtr(), i );
  2153.             StopRecordTime( end );
  2154.             GetBest( start, end, bestClocksGeneric );
  2155.         }
  2156.         tst = x;
  2157.         x.Zero();
  2158.  
  2159.         PrintClocks( va( "generic->MatX_LowerTriangularSolve %dx%d", i, i ), 1, bestClocksGeneric );
  2160.  
  2161.         bestClocksSIMD = 0;
  2162.         for ( j = 0; j < NUMTESTS; j++ ) {
  2163.             StartRecordTime( start );
  2164.             p_simd->MatX_LowerTriangularSolve( L, x.ToFloatPtr(), b.ToFloatPtr(), i );
  2165.             StopRecordTime( end );
  2166.             GetBest( start, end, bestClocksSIMD );
  2167.         }
  2168.  
  2169.         result = x.Compare( tst, MATX_LTS_SIMD_EPSILON ) ? "ok" : S_COLOR_RED"X";
  2170.         PrintClocks( va( "   simd->MatX_LowerTriangularSolve %dx%d %s", i, i, result ), 1, bestClocksSIMD, bestClocksGeneric );
  2171.     }
  2172. }
  2173.  
  2174. /*
  2175. ============
  2176. TestMatXLowerTriangularSolveTranspose
  2177. ============
  2178. */
  2179. void TestMatXLowerTriangularSolveTranspose( void ) {
  2180.     int i, j;
  2181.     TIME_TYPE start, end, bestClocksGeneric, bestClocksSIMD;
  2182.     const char *result;
  2183.     idMatX L;
  2184.     idVecX x, b, tst;
  2185.  
  2186.     idLib::common->Printf("====================================\n" );
  2187.  
  2188.     L.Random( MATX_LTS_SOLVE_SIZE, MATX_LTS_SOLVE_SIZE, 0, -1.0f, 1.0f );
  2189.     x.SetSize( MATX_LTS_SOLVE_SIZE );
  2190.     b.Random( MATX_LTS_SOLVE_SIZE, 0, -1.0f, 1.0f );
  2191.  
  2192.     for ( i = 1; i < MATX_LTS_SOLVE_SIZE; i++ ) {
  2193.  
  2194.         x.Zero( i );
  2195.  
  2196.         bestClocksGeneric = 0;
  2197.         for ( j = 0; j < NUMTESTS; j++ ) {
  2198.             StartRecordTime( start );
  2199.             p_generic->MatX_LowerTriangularSolveTranspose( L, x.ToFloatPtr(), b.ToFloatPtr(), i );
  2200.             StopRecordTime( end );
  2201.             GetBest( start, end, bestClocksGeneric );
  2202.         }
  2203.         tst = x;
  2204.         x.Zero();
  2205.  
  2206.         PrintClocks( va( "generic->MatX_LowerTriangularSolveT %dx%d", i, i ), 1, bestClocksGeneric );
  2207.  
  2208.         bestClocksSIMD = 0;
  2209.         for ( j = 0; j < NUMTESTS; j++ ) {
  2210.             StartRecordTime( start );
  2211.             p_simd->MatX_LowerTriangularSolveTranspose( L, x.ToFloatPtr(), b.ToFloatPtr(), i );
  2212.             StopRecordTime( end );
  2213.             GetBest( start, end, bestClocksSIMD );
  2214.         }
  2215.  
  2216.         result = x.Compare( tst, MATX_LTS_SIMD_EPSILON ) ? "ok" : S_COLOR_RED"X";
  2217.         PrintClocks( va( "   simd->MatX_LowerTriangularSolveT %dx%d %s", i, i, result ), 1, bestClocksSIMD, bestClocksGeneric );
  2218.     }
  2219. }
  2220.  
  2221. #define MATX_LDLT_SIMD_EPSILON            0.1f
  2222. #define MATX_LDLT_FACTOR_SOLVE_SIZE        64
  2223.  
  2224. /*
  2225. ============
  2226. TestMatXLDLTFactor
  2227. ============
  2228. */
  2229. void TestMatXLDLTFactor( void ) {
  2230.     int i, j;
  2231.     TIME_TYPE start, end, bestClocksGeneric, bestClocksSIMD;
  2232.     const char *result;
  2233.     idMatX src, original, mat1, mat2;
  2234.     idVecX invDiag1, invDiag2;
  2235.  
  2236.     idLib::common->Printf("====================================\n" );
  2237.  
  2238.     original.SetSize( MATX_LDLT_FACTOR_SOLVE_SIZE, MATX_LDLT_FACTOR_SOLVE_SIZE );
  2239.     src.Random( MATX_LDLT_FACTOR_SOLVE_SIZE, MATX_LDLT_FACTOR_SOLVE_SIZE, 0, -1.0f, 1.0f );
  2240.     src.TransposeMultiply( original, src );
  2241.  
  2242.     for ( i = 1; i < MATX_LDLT_FACTOR_SOLVE_SIZE; i++ ) {
  2243.  
  2244.         bestClocksGeneric = 0;
  2245.         for ( j = 0; j < NUMTESTS; j++ ) {
  2246.             mat1 = original;
  2247.             invDiag1.Zero( MATX_LDLT_FACTOR_SOLVE_SIZE );
  2248.             StartRecordTime( start );
  2249.             p_generic->MatX_LDLTFactor( mat1, invDiag1, i );
  2250.             StopRecordTime( end );
  2251.             GetBest( start, end, bestClocksGeneric );
  2252.         }
  2253.  
  2254.         PrintClocks( va( "generic->MatX_LDLTFactor %dx%d", i, i ), 1, bestClocksGeneric );
  2255.  
  2256.         bestClocksSIMD = 0;
  2257.         for ( j = 0; j < NUMTESTS; j++ ) {
  2258.             mat2 = original;
  2259.             invDiag2.Zero( MATX_LDLT_FACTOR_SOLVE_SIZE );
  2260.             StartRecordTime( start );
  2261.             p_simd->MatX_LDLTFactor( mat2, invDiag2, i );
  2262.             StopRecordTime( end );
  2263.             GetBest( start, end, bestClocksSIMD );
  2264.         }
  2265.  
  2266.         result = mat1.Compare( mat2, MATX_LDLT_SIMD_EPSILON ) && invDiag1.Compare( invDiag2, MATX_LDLT_SIMD_EPSILON ) ? "ok" : S_COLOR_RED"X";
  2267.         PrintClocks( va( "   simd->MatX_LDLTFactor %dx%d %s", i, i, result ), 1, bestClocksSIMD, bestClocksGeneric );
  2268.     }
  2269. }
  2270.  
  2271. /*
  2272. ============
  2273. TestBlendJoints
  2274. ============
  2275. */
  2276. void TestBlendJoints( void ) {
  2277.     int i, j;
  2278.     TIME_TYPE start, end, bestClocksGeneric, bestClocksSIMD;
  2279.     ALIGN16( idJointQuat baseJoints[COUNT]; )
  2280.     ALIGN16( idJointQuat joints1[COUNT]; )
  2281.     ALIGN16( idJointQuat joints2[COUNT]; )
  2282.     ALIGN16( idJointQuat blendJoints[COUNT]; )
  2283.     ALIGN16( int index[COUNT]; )
  2284.     float lerp = 0.3f;
  2285.     const char *result;
  2286.  
  2287.     idRandom srnd( RANDOM_SEED );
  2288.  
  2289.     for ( i = 0; i < COUNT; i++ ) {
  2290.         idAngles angles;
  2291.         angles[0] = srnd.CRandomFloat() * 180.0f;
  2292.         angles[1] = srnd.CRandomFloat() * 180.0f;
  2293.         angles[2] = srnd.CRandomFloat() * 180.0f;
  2294.         baseJoints[i].q = angles.ToQuat();
  2295.         baseJoints[i].t[0] = srnd.CRandomFloat() * 10.0f;
  2296.         baseJoints[i].t[1] = srnd.CRandomFloat() * 10.0f;
  2297.         baseJoints[i].t[2] = srnd.CRandomFloat() * 10.0f;
  2298.         baseJoints[i].w = 0.0f;
  2299.         angles[0] = srnd.CRandomFloat() * 180.0f;
  2300.         angles[1] = srnd.CRandomFloat() * 180.0f;
  2301.         angles[2] = srnd.CRandomFloat() * 180.0f;
  2302.         blendJoints[i].q = angles.ToQuat();
  2303.         blendJoints[i].t[0] = srnd.CRandomFloat() * 10.0f;
  2304.         blendJoints[i].t[1] = srnd.CRandomFloat() * 10.0f;
  2305.         blendJoints[i].t[2] = srnd.CRandomFloat() * 10.0f;
  2306.         blendJoints[i].w = 0.0f;
  2307.         index[i] = i;
  2308.     }
  2309.  
  2310.     bestClocksGeneric = 0;
  2311.     for ( i = 0; i < NUMTESTS; i++ ) {
  2312.         for ( j = 0; j < COUNT; j++ ) {
  2313.             joints1[j] = baseJoints[j];
  2314.         }
  2315.         StartRecordTime( start );
  2316.         p_generic->BlendJoints( joints1, blendJoints, lerp, index, COUNT );
  2317.         StopRecordTime( end );
  2318.         GetBest( start, end, bestClocksGeneric );
  2319.     }
  2320.     PrintClocks( "generic->BlendJoints()", COUNT, bestClocksGeneric );
  2321.  
  2322.     bestClocksSIMD = 0;
  2323.     for ( i = 0; i < NUMTESTS; i++ ) {
  2324.         for ( j = 0; j < COUNT; j++ ) {
  2325.             joints2[j] = baseJoints[j];
  2326.         }
  2327.         StartRecordTime( start );
  2328.         p_simd->BlendJoints( joints2, blendJoints, lerp, index, COUNT );
  2329.         StopRecordTime( end );
  2330.         GetBest( start, end, bestClocksSIMD );
  2331.     }
  2332.  
  2333.     for ( i = 0; i < COUNT; i++ ) {
  2334.         if ( !joints1[i].t.Compare( joints2[i].t, 1e-3f ) ) {
  2335.             break;
  2336.         }
  2337.         if ( !joints1[i].q.Compare( joints2[i].q, 1e-2f ) ) {
  2338.             break;
  2339.         }
  2340.     }
  2341.     result = ( i >= COUNT ) ? "ok" : S_COLOR_RED"X";
  2342.     PrintClocks( va( "   simd->BlendJoints() %s", result ), COUNT, bestClocksSIMD, bestClocksGeneric );
  2343. }
  2344.  
  2345. /*
  2346. ============
  2347. TestConvertJointQuatsToJointMats
  2348. ============
  2349. */
  2350. void TestConvertJointQuatsToJointMats( void ) {
  2351.     int i;
  2352.     TIME_TYPE start, end, bestClocksGeneric, bestClocksSIMD;
  2353.     ALIGN16( idJointQuat baseJoints[COUNT]; )
  2354.     ALIGN16( idJointMat joints1[COUNT]; )
  2355.     ALIGN16( idJointMat joints2[COUNT]; )
  2356.     const char *result;
  2357.  
  2358.     idRandom srnd( RANDOM_SEED );
  2359.  
  2360.     for ( i = 0; i < COUNT; i++ ) {
  2361.         idAngles angles;
  2362.         angles[0] = srnd.CRandomFloat() * 180.0f;
  2363.         angles[1] = srnd.CRandomFloat() * 180.0f;
  2364.         angles[2] = srnd.CRandomFloat() * 180.0f;
  2365.         baseJoints[i].q = angles.ToQuat();
  2366.         baseJoints[i].t[0] = srnd.CRandomFloat() * 10.0f;
  2367.         baseJoints[i].t[1] = srnd.CRandomFloat() * 10.0f;
  2368.         baseJoints[i].t[2] = srnd.CRandomFloat() * 10.0f;
  2369.     }
  2370.  
  2371.     bestClocksGeneric = 0;
  2372.     for ( i = 0; i < NUMTESTS; i++ ) {
  2373.         StartRecordTime( start );
  2374.         p_generic->ConvertJointQuatsToJointMats( joints1, baseJoints, COUNT );
  2375.         StopRecordTime( end );
  2376.         GetBest( start, end, bestClocksGeneric );
  2377.     }
  2378.     PrintClocks( "generic->ConvertJointQuatsToJointMats()", COUNT, bestClocksGeneric );
  2379.  
  2380.     bestClocksSIMD = 0;
  2381.     for ( i = 0; i < NUMTESTS; i++ ) {
  2382.         StartRecordTime( start );
  2383.         p_simd->ConvertJointQuatsToJointMats( joints2, baseJoints, COUNT );
  2384.         StopRecordTime( end );
  2385.         GetBest( start, end, bestClocksSIMD );
  2386.     }
  2387.  
  2388.     for ( i = 0; i < COUNT; i++ ) {
  2389.         if ( !joints1[i].Compare( joints2[i], 1e-4f ) ) {
  2390.             break;
  2391.         }
  2392.     }
  2393.     result = ( i >= COUNT ) ? "ok" : S_COLOR_RED"X";
  2394.     PrintClocks( va( "   simd->ConvertJointQuatsToJointMats() %s", result ), COUNT, bestClocksSIMD, bestClocksGeneric );
  2395. }
  2396.  
  2397. /*
  2398. ============
  2399. TestConvertJointMatsToJointQuats
  2400. ============
  2401. */
  2402. void TestConvertJointMatsToJointQuats( void ) {
  2403.     int i;
  2404.     TIME_TYPE start, end, bestClocksGeneric, bestClocksSIMD;
  2405.     ALIGN16( idJointMat baseJoints[COUNT]; )
  2406.     ALIGN16( idJointQuat joints1[COUNT]; )
  2407.     ALIGN16( idJointQuat joints2[COUNT]; )
  2408.     const char *result;
  2409.  
  2410.     idRandom srnd( RANDOM_SEED );
  2411.  
  2412.     for ( i = 0; i < COUNT; i++ ) {
  2413.         idAngles angles;
  2414.         angles[0] = srnd.CRandomFloat() * 180.0f;
  2415.         angles[1] = srnd.CRandomFloat() * 180.0f;
  2416.         angles[2] = srnd.CRandomFloat() * 180.0f;
  2417.         baseJoints[i].SetRotation( angles.ToMat3() );
  2418.         idVec3 v;
  2419.         v[0] = srnd.CRandomFloat() * 10.0f;
  2420.         v[1] = srnd.CRandomFloat() * 10.0f;
  2421.         v[2] = srnd.CRandomFloat() * 10.0f;
  2422.         baseJoints[i].SetTranslation( v );
  2423.     }
  2424.  
  2425.     bestClocksGeneric = 0;
  2426.     for ( i = 0; i < NUMTESTS; i++ ) {
  2427.         StartRecordTime( start );
  2428.         p_generic->ConvertJointMatsToJointQuats( joints1, baseJoints, COUNT );
  2429.         StopRecordTime( end );
  2430.         GetBest( start, end, bestClocksGeneric );
  2431.     }
  2432.     PrintClocks( "generic->ConvertJointMatsToJointQuats()", COUNT, bestClocksGeneric );
  2433.  
  2434.     bestClocksSIMD = 0;
  2435.     for ( i = 0; i < NUMTESTS; i++ ) {
  2436.         StartRecordTime( start );
  2437.         p_simd->ConvertJointMatsToJointQuats( joints2, baseJoints, COUNT );
  2438.         StopRecordTime( end );
  2439.         GetBest( start, end, bestClocksSIMD );
  2440.     }
  2441.  
  2442.     for ( i = 0; i < COUNT; i++ ) {
  2443.         if ( !joints1[i].q.Compare( joints2[i].q, 1e-4f ) ) {
  2444.             break;
  2445.         }
  2446.         if ( !joints1[i].t.Compare( joints2[i].t, 1e-4f ) ) {
  2447.             break;
  2448.         }
  2449.     }
  2450.     result = ( i >= COUNT ) ? "ok" : S_COLOR_RED"X";
  2451.     PrintClocks( va( "   simd->ConvertJointMatsToJointQuats() %s", result ), COUNT, bestClocksSIMD, bestClocksGeneric );
  2452. }
  2453.  
  2454. /*
  2455. ============
  2456. TestTransformJoints
  2457. ============
  2458. */
  2459. void TestTransformJoints( void ) {
  2460.     int i, j;
  2461.     TIME_TYPE start, end, bestClocksGeneric, bestClocksSIMD;
  2462.     ALIGN16( idJointMat joints[COUNT+1]; )
  2463.     ALIGN16( idJointMat joints1[COUNT+1]; )
  2464.     ALIGN16( idJointMat joints2[COUNT+1]; )
  2465.     ALIGN16( int parents[COUNT+1]; )
  2466.     const char *result;
  2467.  
  2468.     idRandom srnd( RANDOM_SEED );
  2469.  
  2470.     for ( i = 0; i <= COUNT; i++ ) {
  2471.         idAngles angles;
  2472.         angles[0] = srnd.CRandomFloat() * 180.0f;
  2473.         angles[1] = srnd.CRandomFloat() * 180.0f;
  2474.         angles[2] = srnd.CRandomFloat() * 180.0f;
  2475.         joints[i].SetRotation( angles.ToMat3() );
  2476.         idVec3 v;
  2477.         v[0] = srnd.CRandomFloat() * 2.0f;
  2478.         v[1] = srnd.CRandomFloat() * 2.0f;
  2479.         v[2] = srnd.CRandomFloat() * 2.0f;
  2480.         joints[i].SetTranslation( v );
  2481.         parents[i] = i - 1;
  2482.     }
  2483.  
  2484.     bestClocksGeneric = 0;
  2485.     for ( i = 0; i < NUMTESTS; i++ ) {
  2486.         for ( j = 0; j <= COUNT; j++ ) {
  2487.             joints1[j] = joints[j];
  2488.         }
  2489.         StartRecordTime( start );
  2490.         p_generic->TransformJoints( joints1, parents, 1, COUNT );
  2491.         StopRecordTime( end );
  2492.         GetBest( start, end, bestClocksGeneric );
  2493.     }
  2494.     PrintClocks( "generic->TransformJoints()", COUNT, bestClocksGeneric );
  2495.  
  2496.     bestClocksSIMD = 0;
  2497.     for ( i = 0; i < NUMTESTS; i++ ) {
  2498.         for ( j = 0; j <= COUNT; j++ ) {
  2499.             joints2[j] = joints[j];
  2500.         }
  2501.         StartRecordTime( start );
  2502.         p_simd->TransformJoints( joints2, parents, 1, COUNT );
  2503.         StopRecordTime( end );
  2504.         GetBest( start, end, bestClocksSIMD );
  2505.     }
  2506.  
  2507.     for ( i = 0; i < COUNT; i++ ) {
  2508.         if ( !joints1[i+1].Compare( joints2[i+1], 1e-4f ) ) {
  2509.             break;
  2510.         }
  2511.     }
  2512.     result = ( i >= COUNT ) ? "ok" : S_COLOR_RED"X";
  2513.     PrintClocks( va( "   simd->TransformJoints() %s", result ), COUNT, bestClocksSIMD, bestClocksGeneric );
  2514. }
  2515.  
  2516. /*
  2517. ============
  2518. TestUntransformJoints
  2519. ============
  2520. */
  2521. void TestUntransformJoints( void ) {
  2522.     int i, j;
  2523.     TIME_TYPE start, end, bestClocksGeneric, bestClocksSIMD;
  2524.     ALIGN16( idJointMat joints[COUNT+1]; )
  2525.     ALIGN16( idJointMat joints1[COUNT+1]; )
  2526.     ALIGN16( idJointMat joints2[COUNT+1]; )
  2527.     ALIGN16( int parents[COUNT+1]; )
  2528.     const char *result;
  2529.  
  2530.     idRandom srnd( RANDOM_SEED );
  2531.  
  2532.     for ( i = 0; i <= COUNT; i++ ) {
  2533.         idAngles angles;
  2534.         angles[0] = srnd.CRandomFloat() * 180.0f;
  2535.         angles[1] = srnd.CRandomFloat() * 180.0f;
  2536.         angles[2] = srnd.CRandomFloat() * 180.0f;
  2537.         joints[i].SetRotation( angles.ToMat3() );
  2538.         idVec3 v;
  2539.         v[0] = srnd.CRandomFloat() * 2.0f;
  2540.         v[1] = srnd.CRandomFloat() * 2.0f;
  2541.         v[2] = srnd.CRandomFloat() * 2.0f;
  2542.         joints[i].SetTranslation( v );
  2543.         parents[i] = i - 1;
  2544.     }
  2545.  
  2546.     bestClocksGeneric = 0;
  2547.     for ( i = 0; i < NUMTESTS; i++ ) {
  2548.         for ( j = 0; j <= COUNT; j++ ) {
  2549.             joints1[j] = joints[j];
  2550.         }
  2551.         StartRecordTime( start );
  2552.         p_generic->UntransformJoints( joints1, parents, 1, COUNT );
  2553.         StopRecordTime( end );
  2554.         GetBest( start, end, bestClocksGeneric );
  2555.     }
  2556.     PrintClocks( "generic->UntransformJoints()", COUNT, bestClocksGeneric );
  2557.  
  2558.     bestClocksSIMD = 0;
  2559.     for ( i = 0; i < NUMTESTS; i++ ) {
  2560.         for ( j = 0; j <= COUNT; j++ ) {
  2561.             joints2[j] = joints[j];
  2562.         }
  2563.         StartRecordTime( start );
  2564.         p_simd->UntransformJoints( joints2, parents, 1, COUNT );
  2565.         StopRecordTime( end );
  2566.         GetBest( start, end, bestClocksSIMD );
  2567.     }
  2568.  
  2569.     for ( i = 0; i < COUNT; i++ ) {
  2570.         if ( !joints1[i+1].Compare( joints2[i+1], 1e-4f ) ) {
  2571.             break;
  2572.         }
  2573.     }
  2574.     result = ( i >= COUNT ) ? "ok" : S_COLOR_RED"X";
  2575.     PrintClocks( va( "   simd->UntransformJoints() %s", result ), COUNT, bestClocksSIMD, bestClocksGeneric );
  2576. }
  2577.  
  2578. /*
  2579. ============
  2580. TestTransformVertsNew
  2581. ============
  2582. */
  2583. #undef NUMJOINTS
  2584. #undef NUMVERTS
  2585.  
  2586. #define NUMJOINTS            64
  2587. #define NUMVERTS            COUNT
  2588. #define NUMWEIGHTSPERVERT    2
  2589. #define NUMWEIGHTS            (NUMVERTS*NUMWEIGHTSPERVERT)
  2590.  
  2591. void TestTransformVertsNew( void ) {
  2592.     int i;
  2593.     TIME_TYPE start, end, bestClocksGeneric, bestClocksSIMD;
  2594.     ALIGN16( idDrawVert drawVerts1[NUMVERTS]; )
  2595.     ALIGN16( idDrawVert drawVerts2[NUMVERTS]; )
  2596.     ALIGN16( idJointMat joints[NUMJOINTS]; )
  2597.     ALIGN16( idVec4 base[NUMWEIGHTS*3]; )
  2598.     ALIGN16( jointWeight_t weights[NUMWEIGHTS]; )
  2599.     idBounds bounds1, bounds2;
  2600.     const char *result;
  2601.  
  2602.     idRandom srnd( RANDOM_SEED );
  2603.  
  2604.     for ( i = 0; i < NUMJOINTS; i++ ) {
  2605.         idAngles angles;
  2606.         angles[0] = srnd.CRandomFloat() * 180.0f;
  2607.         angles[1] = srnd.CRandomFloat() * 180.0f;
  2608.         angles[2] = srnd.CRandomFloat() * 180.0f;
  2609.         joints[i].SetRotation( angles.ToMat3() );
  2610.         idVec3 v;
  2611.         v[0] = srnd.CRandomFloat() * 2.0f;
  2612.         v[1] = srnd.CRandomFloat() * 2.0f;
  2613.         v[2] = srnd.CRandomFloat() * 2.0f;
  2614.         joints[i].SetTranslation( v );
  2615.     }
  2616.  
  2617.     for ( i = 0; i < NUMWEIGHTS*3; i++ ) {
  2618.         base[i][0] = srnd.CRandomFloat() * 2.0f;
  2619.         base[i][1] = srnd.CRandomFloat() * 2.0f;
  2620.         base[i][2] = srnd.CRandomFloat() * 2.0f;
  2621.         base[i][3] = srnd.CRandomFloat();
  2622.     }
  2623.  
  2624.     for ( i = 0; i < NUMWEIGHTS; i++ ) {
  2625.         weights[i].weight = srnd.CRandomFloat();
  2626.         weights[i].jointMatOffset = idMath::ClampInt( 0, NUMJOINTS-1, i * NUMJOINTS / NUMWEIGHTS + 0 ) * JOINTMAT_SIZE;
  2627.         weights[i].nextVertexOffset = ( NUMWEIGHTSPERVERT - ( i % NUMWEIGHTSPERVERT ) ) * JOINTWEIGHT_SIZE;
  2628.     }
  2629.  
  2630.     bestClocksGeneric = 0;
  2631.     for ( i = 0; i < NUMTESTS; i++ ) {
  2632.         StartRecordTime( start );
  2633.         p_generic->TransformVertsNew( drawVerts1, NUMVERTS, bounds1, joints, base, weights, NUMWEIGHTS );
  2634.         StopRecordTime( end );
  2635.         GetBest( start, end, bestClocksGeneric );
  2636.     }
  2637.     PrintClocks( "generic->TransformVertsNew()", NUMVERTS, bestClocksGeneric );
  2638.  
  2639.     bestClocksSIMD = 0;
  2640.     for ( i = 0; i < NUMTESTS; i++ ) {
  2641.         StartRecordTime( start );
  2642.         p_simd->TransformVertsNew( drawVerts2, NUMVERTS, bounds2, joints, base, weights, NUMWEIGHTS );
  2643.         StopRecordTime( end );
  2644.         GetBest( start, end, bestClocksSIMD );
  2645.     }
  2646.  
  2647.     for ( i = 0; i < NUMVERTS; i++ ) {
  2648.         if ( !drawVerts1[i].xyz.Compare( drawVerts2[i].xyz, 0.5f ) ) {
  2649.             break;
  2650.         }
  2651.     }
  2652.     result = ( i >= NUMVERTS && bounds1.Compare( bounds2, 1e-4f ) ) ? "ok" : S_COLOR_RED"X";
  2653.     PrintClocks( va( "   simd->TransformVertsNew() %s", result ), NUMVERTS, bestClocksSIMD, bestClocksGeneric );
  2654.  
  2655.     bestClocksGeneric = 0;
  2656.     for ( i = 0; i < NUMTESTS; i++ ) {
  2657.         StartRecordTime( start );
  2658.         p_generic->TransformVertsAndTangents( drawVerts1, NUMVERTS, bounds1, joints, base, weights, NUMWEIGHTS );
  2659.         StopRecordTime( end );
  2660.         GetBest( start, end, bestClocksGeneric );
  2661.     }
  2662.     PrintClocks( "generic->TransformVertsAndTangents()", NUMVERTS, bestClocksGeneric );
  2663.  
  2664.     bestClocksSIMD = 0;
  2665.     for ( i = 0; i < NUMTESTS; i++ ) {
  2666.         StartRecordTime( start );
  2667.         p_simd->TransformVertsAndTangents( drawVerts2, NUMVERTS, bounds2, joints, base, weights, NUMWEIGHTS );
  2668.         StopRecordTime( end );
  2669.         GetBest( start, end, bestClocksSIMD );
  2670.     }
  2671.  
  2672.     for ( i = 0; i < NUMVERTS; i++ ) {
  2673.         if ( !drawVerts1[i].xyz.Compare( drawVerts2[i].xyz, 0.5f ) ) {
  2674.             break;
  2675.         }
  2676.         if ( !drawVerts1[i].normal.Compare( drawVerts2[i].normal, 0.1f ) ) {
  2677.             break;
  2678.         }
  2679.         if ( !drawVerts1[i].tangents[0].Compare( drawVerts2[i].tangents[0], 0.1f ) ) {
  2680.             break;
  2681.         }
  2682.     }
  2683.     result = ( i >= NUMVERTS && bounds1.Compare( bounds2, 1e-4f ) ) ? "ok" : S_COLOR_RED"X";
  2684.     PrintClocks( va( "   simd->TransformVertsAndTangents() %s", result ), NUMVERTS, bestClocksSIMD, bestClocksGeneric );
  2685.  
  2686.     bestClocksGeneric = 0;
  2687.     for ( i = 0; i < NUMTESTS; i++ ) {
  2688.         StartRecordTime( start );
  2689.         p_generic->TransformVertsAndTangentsFast( drawVerts1, NUMVERTS, bounds1, joints, base, weights, NUMWEIGHTS );
  2690.         StopRecordTime( end );
  2691.         GetBest( start, end, bestClocksGeneric );
  2692.     }
  2693.     PrintClocks( "generic->TransformVertsAndTangentsFast()", NUMVERTS, bestClocksGeneric );
  2694.  
  2695.     bestClocksSIMD = 0;
  2696.     for ( i = 0; i < NUMTESTS; i++ ) {
  2697.         StartRecordTime( start );
  2698.         p_simd->TransformVertsAndTangentsFast( drawVerts2, NUMVERTS, bounds2, joints, base, weights, NUMWEIGHTS );
  2699.         StopRecordTime( end );
  2700.         GetBest( start, end, bestClocksSIMD );
  2701.     }
  2702.  
  2703.     for ( i = 0; i < NUMVERTS; i++ ) {
  2704.         if ( !drawVerts1[i].xyz.Compare( drawVerts2[i].xyz, 0.5f ) ) {
  2705.             break;
  2706.         }
  2707.         if ( !drawVerts1[i].normal.Compare( drawVerts2[i].normal, 0.1f ) ) {
  2708.             break;
  2709.         }
  2710.         if ( !drawVerts1[i].tangents[0].Compare( drawVerts2[i].tangents[0], 0.1f ) ) {
  2711.             break;
  2712.         }
  2713.     }
  2714.     result = ( i >= NUMVERTS && bounds1.Compare( bounds2, 1e-4f ) ) ? "ok" : S_COLOR_RED"X";
  2715.     PrintClocks( va( "   simd->TransformVertsAndTangentsFast() %s", result ), NUMVERTS, bestClocksSIMD, bestClocksGeneric );
  2716. }
  2717.  
  2718. /*
  2719. ============
  2720. TestTracePointCull
  2721. ============
  2722. */
  2723. void TestTracePointCull( void ) {
  2724.     int i, j;
  2725.     TIME_TYPE start, end, bestClocksGeneric, bestClocksSIMD;
  2726.     ALIGN16( idPlane planes[4]; )
  2727.     ALIGN16( idDrawVert drawVerts[COUNT]; )
  2728.     ALIGN16( byte cullBits1[COUNT]; )
  2729.     ALIGN16( byte cullBits2[COUNT]; )
  2730.     byte totalOr1 = 0, totalOr2 = 0;
  2731.     const char *result;
  2732.  
  2733.     idRandom srnd( RANDOM_SEED );
  2734.  
  2735.     planes[0].SetNormal( idVec3(  1,  0, 0 ) );
  2736.     planes[1].SetNormal( idVec3( -1,  0, 0 ) );
  2737.     planes[2].SetNormal( idVec3(  0,  1, 0 ) );
  2738.     planes[3].SetNormal( idVec3(  0, -1, 0 ) );
  2739.     planes[0][3] = -5.3f;
  2740.     planes[1][3] = 5.3f;
  2741.     planes[2][3] = -3.4f;
  2742.     planes[3][3] = 3.4f;
  2743.  
  2744.     for ( i = 0; i < COUNT; i++ ) {
  2745.         for ( j = 0; j < 3; j++ ) {
  2746.             drawVerts[i].xyz[j] = srnd.CRandomFloat() * 10.0f;
  2747.         }
  2748.     }
  2749.  
  2750.     bestClocksGeneric = 0;
  2751.     for ( i = 0; i < NUMTESTS; i++ ) {
  2752.         StartRecordTime( start );
  2753.         p_generic->TracePointCull( cullBits1, totalOr1, 0.0f, planes, drawVerts, COUNT );
  2754.         StopRecordTime( end );
  2755.         GetBest( start, end, bestClocksGeneric );
  2756.     }
  2757.     PrintClocks( "generic->TracePointCull()", COUNT, bestClocksGeneric );
  2758.  
  2759.     bestClocksSIMD = 0;
  2760.     for ( i = 0; i < NUMTESTS; i++ ) {
  2761.         StartRecordTime( start );
  2762.         p_simd->TracePointCull( cullBits2, totalOr2, 0.0f, planes, drawVerts, COUNT );
  2763.         StopRecordTime( end );
  2764.         GetBest( start, end, bestClocksSIMD );
  2765.     }
  2766.  
  2767.     for ( i = 0; i < COUNT; i++ ) {
  2768.         if ( cullBits1[i] != cullBits2[i] ) {
  2769.             break;
  2770.         }
  2771.     }
  2772.     result = ( i >= COUNT && totalOr1 == totalOr2 ) ? "ok" : S_COLOR_RED"X";
  2773.     PrintClocks( va( "   simd->TracePointCull() %s", result ), COUNT, bestClocksSIMD, bestClocksGeneric );
  2774. }
  2775.  
  2776. /*
  2777. ============
  2778. TestDecalPointCull
  2779. ============
  2780. */
  2781. void TestDecalPointCull( void ) {
  2782.     int i, j;
  2783.     TIME_TYPE start, end, bestClocksGeneric, bestClocksSIMD;
  2784.     ALIGN16( idPlane planes[6]; )
  2785.     ALIGN16( idDrawVert drawVerts[COUNT]; )
  2786.     ALIGN16( byte cullBits1[COUNT]; )
  2787.     ALIGN16( byte cullBits2[COUNT]; )
  2788.     const char *result;
  2789.  
  2790.     idRandom srnd( RANDOM_SEED );
  2791.  
  2792.     planes[0].SetNormal( idVec3(  1,  0,  0 ) );
  2793.     planes[1].SetNormal( idVec3( -1,  0,  0 ) );
  2794.     planes[2].SetNormal( idVec3(  0,  1,  0 ) );
  2795.     planes[3].SetNormal( idVec3(  0, -1,  0 ) );
  2796.     planes[4].SetNormal( idVec3(  0,  0,  1 ) );
  2797.     planes[5].SetNormal( idVec3(  0,  0, -1 ) );
  2798.     planes[0][3] = -5.3f;
  2799.     planes[1][3] = 5.3f;
  2800.     planes[2][3] = -4.4f;
  2801.     planes[3][3] = 4.4f;
  2802.     planes[4][3] = -3.5f;
  2803.     planes[5][3] = 3.5f;
  2804.  
  2805.     for ( i = 0; i < COUNT; i++ ) {
  2806.         for ( j = 0; j < 3; j++ ) {
  2807.             drawVerts[i].xyz[j] = srnd.CRandomFloat() * 10.0f;
  2808.         }
  2809.     }
  2810.  
  2811.     bestClocksGeneric = 0;
  2812.     for ( i = 0; i < NUMTESTS; i++ ) {
  2813.         StartRecordTime( start );
  2814.         p_generic->DecalPointCull( cullBits1, planes, drawVerts, COUNT );
  2815.         StopRecordTime( end );
  2816.         GetBest( start, end, bestClocksGeneric );
  2817.     }
  2818.     PrintClocks( "generic->DecalPointCull()", COUNT, bestClocksGeneric );
  2819.  
  2820.     bestClocksSIMD = 0;
  2821.     for ( i = 0; i < NUMTESTS; i++ ) {
  2822.         StartRecordTime( start );
  2823.         p_simd->DecalPointCull( cullBits2, planes, drawVerts, COUNT );
  2824.         StopRecordTime( end );
  2825.         GetBest( start, end, bestClocksSIMD );
  2826.     }
  2827.  
  2828.     for ( i = 0; i < COUNT; i++ ) {
  2829.         if ( cullBits1[i] != cullBits2[i] ) {
  2830.             break;
  2831.         }
  2832.     }
  2833.     result = ( i >= COUNT ) ? "ok" : S_COLOR_RED"X";
  2834.     PrintClocks( va( "   simd->DecalPointCull() %s", result ), COUNT, bestClocksSIMD, bestClocksGeneric );
  2835. }
  2836.  
  2837. /*
  2838. ============
  2839. TestOverlayPointCull
  2840. ============
  2841. */
  2842. void TestOverlayPointCull( void ) {
  2843.     int i, j;
  2844.     TIME_TYPE start, end, bestClocksGeneric, bestClocksSIMD;
  2845.     ALIGN16( idPlane planes[2]; )
  2846.     ALIGN16( idDrawVert drawVerts[COUNT]; )
  2847.     ALIGN16( byte cullBits1[COUNT]; )
  2848.     ALIGN16( byte cullBits2[COUNT]; )
  2849.     ALIGN16( idVec2 texCoords1[COUNT]; )
  2850.     ALIGN16( idVec2 texCoords2[COUNT]; )
  2851.     const char *result;
  2852.  
  2853.     idRandom srnd( RANDOM_SEED );
  2854.  
  2855.     planes[0].SetNormal( idVec3( 0.3f, 0.2f, 0.9f ) );
  2856.     planes[1].SetNormal( idVec3( 0.9f, 0.2f, 0.3f ) );
  2857.     planes[0][3] = -5.3f;
  2858.     planes[1][3] = -4.3f;
  2859.  
  2860.     for ( i = 0; i < COUNT; i++ ) {
  2861.         for ( j = 0; j < 3; j++ ) {
  2862.             drawVerts[i].xyz[j] = srnd.CRandomFloat() * 10.0f;
  2863.         }
  2864.     }
  2865.  
  2866.     bestClocksGeneric = 0;
  2867.     for ( i = 0; i < NUMTESTS; i++ ) {
  2868.         StartRecordTime( start );
  2869.         p_generic->OverlayPointCull( cullBits1, texCoords1, planes, drawVerts, COUNT );
  2870.         StopRecordTime( end );
  2871.         GetBest( start, end, bestClocksGeneric );
  2872.     }
  2873.     PrintClocks( "generic->OverlayPointCull()", COUNT, bestClocksGeneric );
  2874.  
  2875.     bestClocksSIMD = 0;
  2876.     for ( i = 0; i < NUMTESTS; i++ ) {
  2877.         StartRecordTime( start );
  2878.         p_simd->OverlayPointCull( cullBits2, texCoords2, planes, drawVerts, COUNT );
  2879.         StopRecordTime( end );
  2880.         GetBest( start, end, bestClocksSIMD );
  2881.     }
  2882.  
  2883.     for ( i = 0; i < COUNT; i++ ) {
  2884.         if ( cullBits1[i] != cullBits2[i] ) {
  2885.             break;
  2886.         }
  2887.         if ( !texCoords1[i].Compare( texCoords2[i], 1e-4f ) ) {
  2888.             break;
  2889.         }
  2890.     }
  2891.     result = ( i >= COUNT ) ? "ok" : S_COLOR_RED"X";
  2892.     PrintClocks( va( "   simd->OverlayPointCull() %s", result ), COUNT, bestClocksSIMD, bestClocksGeneric );
  2893. }
  2894.  
  2895. /*
  2896. ============
  2897. TestDeriveTriPlanes
  2898. ============
  2899. */
  2900. void TestDeriveTriPlanes( void ) {
  2901.     int i, j;
  2902.     TIME_TYPE start, end, bestClocksGeneric, bestClocksSIMD;
  2903.     ALIGN16( idDrawVert drawVerts1[COUNT]; )
  2904.     ALIGN16( idDrawVert drawVerts2[COUNT]; )
  2905.     ALIGN16( idPlane planes1[COUNT]; )
  2906.     ALIGN16( idPlane planes2[COUNT]; )
  2907.     ALIGN16( int indexes[COUNT*3]; )
  2908.     const char *result;
  2909.  
  2910.     idRandom srnd( RANDOM_SEED );
  2911.  
  2912.     for ( i = 0; i < COUNT; i++ ) {
  2913.         for ( j = 0; j < 3; j++ ) {
  2914.             drawVerts1[i].xyz[j] = srnd.CRandomFloat() * 10.0f;
  2915.         }
  2916.         for ( j = 0; j < 2; j++ ) {
  2917.             drawVerts1[i].st[j] = srnd.CRandomFloat();
  2918.         }
  2919.         drawVerts2[i] = drawVerts1[i];
  2920.     }
  2921.  
  2922.     for ( i = 0; i < COUNT; i++ ) {
  2923.         indexes[i*3+0] = ( i + 0 ) % COUNT;
  2924.         indexes[i*3+1] = ( i + 1 ) % COUNT;
  2925.         indexes[i*3+2] = ( i + 2 ) % COUNT;
  2926.     }
  2927.  
  2928.     bestClocksGeneric = 0;
  2929.     for ( i = 0; i < NUMTESTS; i++ ) {
  2930.         StartRecordTime( start );
  2931.         p_generic->DeriveTriPlanes( planes1, drawVerts1, COUNT, indexes, COUNT*3 );
  2932.         StopRecordTime( end );
  2933.         GetBest( start, end, bestClocksGeneric );
  2934.     }
  2935.     PrintClocks( "generic->DeriveTriPlanes()", COUNT, bestClocksGeneric );
  2936.  
  2937.     bestClocksSIMD = 0;
  2938.     for ( i = 0; i < NUMTESTS; i++ ) {
  2939.         StartRecordTime( start );
  2940.         p_simd->DeriveTriPlanes( planes2, drawVerts2, COUNT, indexes, COUNT*3 );
  2941.         StopRecordTime( end );
  2942.         GetBest( start, end, bestClocksSIMD );
  2943.     }
  2944.  
  2945.     for ( i = 0; i < COUNT; i++ ) {
  2946.         if ( !planes1[i].Compare( planes2[i], 1e-1f, 1e-1f ) ) {
  2947.             break;
  2948.         }
  2949.     }
  2950.     result = ( i >= COUNT ) ? "ok" : S_COLOR_RED"X";
  2951.     PrintClocks( va( "   simd->DeriveTriPlanes() %s", result ), COUNT, bestClocksSIMD, bestClocksGeneric );
  2952. }
  2953.  
  2954. /*
  2955. ============
  2956. TestDeriveTangents
  2957. ============
  2958. */
  2959. void TestDeriveTangents( void ) {
  2960.     int i, j;
  2961.     TIME_TYPE start, end, bestClocksGeneric, bestClocksSIMD;
  2962.     ALIGN16( idDrawVert drawVerts1[COUNT]; )
  2963.     ALIGN16( idDrawVert drawVerts2[COUNT]; )
  2964.     ALIGN16( idPlane planes1[COUNT]; )
  2965.     ALIGN16( idPlane planes2[COUNT]; )
  2966.     ALIGN16( int indexes[COUNT*3]; )
  2967.     const char *result;
  2968.  
  2969.     idRandom srnd( RANDOM_SEED );
  2970.  
  2971.     for ( i = 0; i < COUNT; i++ ) {
  2972.         for ( j = 0; j < 3; j++ ) {
  2973.             drawVerts1[i].xyz[j] = srnd.CRandomFloat() * 10.0f;
  2974.         }
  2975.         for ( j = 0; j < 2; j++ ) {
  2976.             drawVerts1[i].st[j] = srnd.CRandomFloat();
  2977.         }
  2978.         drawVerts2[i] = drawVerts1[i];
  2979.     }
  2980.  
  2981.     for ( i = 0; i < COUNT; i++ ) {
  2982.         indexes[i*3+0] = ( i + 0 ) % COUNT;
  2983.         indexes[i*3+1] = ( i + 1 ) % COUNT;
  2984.         indexes[i*3+2] = ( i + 2 ) % COUNT;
  2985.     }
  2986.  
  2987.     bestClocksGeneric = 0;
  2988.     for ( i = 0; i < NUMTESTS; i++ ) {
  2989.         StartRecordTime( start );
  2990.         p_generic->DeriveTangents( planes1, drawVerts1, COUNT, indexes, COUNT*3 );
  2991.         StopRecordTime( end );
  2992.         GetBest( start, end, bestClocksGeneric );
  2993.     }
  2994.     PrintClocks( "generic->DeriveTangents()", COUNT, bestClocksGeneric );
  2995.  
  2996.     bestClocksSIMD = 0;
  2997.     for ( i = 0; i < NUMTESTS; i++ ) {
  2998.         StartRecordTime( start );
  2999.         p_simd->DeriveTangents( planes2, drawVerts2, COUNT, indexes, COUNT*3 );
  3000.         StopRecordTime( end );
  3001.         GetBest( start, end, bestClocksSIMD );
  3002.     }
  3003.  
  3004.     for ( i = 0; i < COUNT; i++ ) {
  3005.         idVec3 v1, v2;
  3006.  
  3007.         v1 = drawVerts1[i].normal;
  3008.         v1.Normalize();
  3009.         v2 = drawVerts2[i].normal;
  3010.         v2.Normalize();
  3011.         if ( !v1.Compare( v2, 1e-1f ) ) {
  3012.             break;
  3013.         }
  3014.         v1 = drawVerts1[i].tangents[0];
  3015.         v1.Normalize();
  3016.         v2 = drawVerts2[i].tangents[0];
  3017.         v2.Normalize();
  3018.         if ( !v1.Compare( v2, 1e-1f ) ) {
  3019.             break;
  3020.         }
  3021.         v1 = drawVerts1[i].tangents[1];
  3022.         v1.Normalize();
  3023.         v2 = drawVerts2[i].tangents[1];
  3024.         v2.Normalize();
  3025.         if ( !v1.Compare( v2, 1e-1f ) ) {
  3026.             break;
  3027.         }
  3028.         if ( !planes1[i].Compare( planes2[i], 1e-1f, 1e-1f ) ) {
  3029.             break;
  3030.         }
  3031.     }
  3032.     result = ( i >= COUNT ) ? "ok" : S_COLOR_RED"X";
  3033.     PrintClocks( va( "   simd->DeriveTangents() %s", result ), COUNT, bestClocksSIMD, bestClocksGeneric );
  3034. }
  3035.  
  3036. /*
  3037. ============
  3038. TestDeriveUnsmoothedTangents
  3039. ============
  3040. */
  3041. void TestDeriveUnsmoothedTangents( void ) {
  3042.     int i, j;
  3043.     TIME_TYPE start, end, bestClocksGeneric, bestClocksSIMD;
  3044.     ALIGN16( idDrawVert drawVerts1[COUNT]; )
  3045.     ALIGN16( idDrawVert drawVerts2[COUNT]; )
  3046.     ALIGN16( dominantTri_s dominantTris[COUNT] );
  3047.     const char *result;
  3048.  
  3049.     idRandom srnd( RANDOM_SEED );
  3050.  
  3051.     for ( i = 0; i < COUNT; i++ ) {
  3052.         for ( j = 0; j < 3; j++ ) {
  3053.             drawVerts1[i].xyz[j] = srnd.CRandomFloat() * 10.0f;
  3054.         }
  3055.         for ( j = 0; j < 2; j++ ) {
  3056.             drawVerts1[i].st[j] = srnd.CRandomFloat();
  3057.         }
  3058.         drawVerts2[i] = drawVerts1[i];
  3059.  
  3060.         dominantTris[i].v2 = ( i + 1 + srnd.RandomInt( 8 ) ) % COUNT;
  3061.         dominantTris[i].v3 = ( i + 9 + srnd.RandomInt( 8 ) ) % COUNT;
  3062.         dominantTris[i].normalizationScale[0] = srnd.CRandomFloat();
  3063.         dominantTris[i].normalizationScale[1] = srnd.CRandomFloat();
  3064.         dominantTris[i].normalizationScale[2] = srnd.CRandomFloat();
  3065.     }
  3066.  
  3067.     bestClocksGeneric = 0;
  3068.     for ( i = 0; i < NUMTESTS; i++ ) {
  3069.         StartRecordTime( start );
  3070.         p_generic->DeriveUnsmoothedTangents( drawVerts1, dominantTris, COUNT );
  3071.         StopRecordTime( end );
  3072.         GetBest( start, end, bestClocksGeneric );
  3073.     }
  3074.     PrintClocks( "generic->DeriveUnsmoothedTangents()", COUNT, bestClocksGeneric );
  3075.  
  3076.     bestClocksSIMD = 0;
  3077.     for ( i = 0; i < NUMTESTS; i++ ) {
  3078.         StartRecordTime( start );
  3079.         p_simd->DeriveUnsmoothedTangents( drawVerts2, dominantTris, COUNT );
  3080.         StopRecordTime( end );
  3081.         GetBest( start, end, bestClocksSIMD );
  3082.     }
  3083.  
  3084.     for ( i = 0; i < COUNT; i++ ) {
  3085.         idVec3 v1, v2;
  3086.  
  3087.         v1 = drawVerts1[i].normal;
  3088.         v1.Normalize();
  3089.         v2 = drawVerts2[i].normal;
  3090.         v2.Normalize();
  3091.         if ( !v1.Compare( v2, 1e-1f ) ) {
  3092.             break;
  3093.         }
  3094.         v1 = drawVerts1[i].tangents[0];
  3095.         v1.Normalize();
  3096.         v2 = drawVerts2[i].tangents[0];
  3097.         v2.Normalize();
  3098.         if ( !v1.Compare( v2, 1e-1f ) ) {
  3099.             break;
  3100.         }
  3101.         v1 = drawVerts1[i].tangents[1];
  3102.         v1.Normalize();
  3103.         v2 = drawVerts2[i].tangents[1];
  3104.         v2.Normalize();
  3105.         if ( !v1.Compare( v2, 1e-1f ) ) {
  3106.             break;
  3107.         }
  3108.     }
  3109.     result = ( i >= COUNT ) ? "ok" : S_COLOR_RED"X";
  3110.     PrintClocks( va( "   simd->DeriveUnsmoothedTangents() %s", result ), COUNT, bestClocksSIMD, bestClocksGeneric );
  3111. }
  3112.  
  3113. /*
  3114. ============
  3115. TestNormalizeTangents
  3116. ============
  3117. */
  3118. void TestNormalizeTangents( void ) {
  3119.     int i, j;
  3120.     TIME_TYPE start, end, bestClocksGeneric, bestClocksSIMD;
  3121.     ALIGN16( idDrawVert drawVerts1[COUNT]; )
  3122.     ALIGN16( idDrawVert drawVerts2[COUNT]; )
  3123.     const char *result;
  3124.  
  3125.     idRandom srnd( RANDOM_SEED );
  3126.  
  3127.     for ( i = 0; i < COUNT; i++ ) {
  3128.         for ( j = 0; j < 3; j++ ) {
  3129.             drawVerts1[i].normal[j] = srnd.CRandomFloat() * 10.0f;
  3130.             drawVerts1[i].tangents[0][j] = srnd.CRandomFloat() * 10.0f;
  3131.             drawVerts1[i].tangents[1][j] = srnd.CRandomFloat() * 10.0f;
  3132.         }
  3133.         drawVerts2[i] = drawVerts1[i];
  3134.     }
  3135.  
  3136.     bestClocksGeneric = 0;
  3137.     for ( i = 0; i < NUMTESTS; i++ ) {
  3138.         StartRecordTime( start );
  3139.         p_generic->NormalizeTangents( drawVerts1, COUNT );
  3140.         StopRecordTime( end );
  3141.         GetBest( start, end, bestClocksGeneric );
  3142.     }
  3143.     PrintClocks( "generic->NormalizeTangents()", COUNT, bestClocksGeneric );
  3144.  
  3145.     bestClocksSIMD = 0;
  3146.     for ( i = 0; i < NUMTESTS; i++ ) {
  3147.         StartRecordTime( start );
  3148.         p_simd->NormalizeTangents( drawVerts2, COUNT );
  3149.         StopRecordTime( end );
  3150.         GetBest( start, end, bestClocksSIMD );
  3151.     }
  3152.  
  3153.     for ( i = 0; i < COUNT; i++ ) {
  3154.         if ( !drawVerts1[i].normal.Compare( drawVerts2[i].normal, 1e-2f ) ) {
  3155.             break;
  3156.         }
  3157.         if ( !drawVerts1[i].tangents[0].Compare( drawVerts2[i].tangents[0], 1e-2f ) ) {
  3158.             break;
  3159.         }
  3160.         if ( !drawVerts1[i].tangents[1].Compare( drawVerts2[i].tangents[1], 1e-2f ) ) {
  3161.             break;
  3162.         }
  3163.         
  3164.         // since we're doing a lot of unaligned work, added this check to 
  3165.         // make sure xyz wasn't getting overwritten
  3166.         if ( !drawVerts1[i].xyz.Compare( drawVerts2[i].xyz, 1e-2f ) ) {
  3167.             break;
  3168.         }
  3169.     }
  3170.     result = ( i >= COUNT ) ? "ok" : S_COLOR_RED"X";
  3171.     PrintClocks( va( "   simd->NormalizeTangents() %s", result ), COUNT, bestClocksSIMD, bestClocksGeneric );
  3172. }
  3173.  
  3174. /*
  3175. ============
  3176. TestGetTextureSpaceLightVectors
  3177. ============
  3178. */
  3179. void TestGetTextureSpaceLightVectors( void ) {
  3180.     int i, j;
  3181.     TIME_TYPE start, end, bestClocksGeneric, bestClocksSIMD;
  3182.     ALIGN16( idDrawVert drawVerts[COUNT]; )
  3183.     ALIGN16( idVec4 texCoords1[COUNT]; )
  3184.     ALIGN16( idVec4 texCoords2[COUNT]; )
  3185.     ALIGN16( int indexes[COUNT*3]; )
  3186.     ALIGN16( idVec3 lightVectors1[COUNT]; )
  3187.     ALIGN16( idVec3 lightVectors2[COUNT]; )
  3188.     idVec3 lightOrigin;
  3189.     const char *result;
  3190.  
  3191.     idRandom srnd( RANDOM_SEED );
  3192.  
  3193.     for ( i = 0; i < COUNT; i++ ) {
  3194.         for ( j = 0; j < 3; j++ ) {
  3195.             drawVerts[i].xyz[j] = srnd.CRandomFloat() * 100.0f;
  3196.             drawVerts[i].normal[j] = srnd.CRandomFloat();
  3197.             drawVerts[i].tangents[0][j] = srnd.CRandomFloat();
  3198.             drawVerts[i].tangents[1][j] = srnd.CRandomFloat();
  3199.         }
  3200.     }
  3201.  
  3202.     for ( i = 0; i < COUNT; i++ ) {
  3203.         indexes[i*3+0] = ( i + 0 ) % COUNT;
  3204.         indexes[i*3+1] = ( i + 1 ) % COUNT;
  3205.         indexes[i*3+2] = ( i + 2 ) % COUNT;
  3206.     }
  3207.  
  3208.     lightOrigin[0] = srnd.CRandomFloat() * 100.0f;
  3209.     lightOrigin[1] = srnd.CRandomFloat() * 100.0f;
  3210.     lightOrigin[2] = srnd.CRandomFloat() * 100.0f;
  3211.  
  3212.     bestClocksGeneric = 0;
  3213.     for ( i = 0; i < NUMTESTS; i++ ) {
  3214.         StartRecordTime( start );
  3215.         p_generic->CreateTextureSpaceLightVectors( lightVectors1, lightOrigin, drawVerts, COUNT, indexes, COUNT*3 );
  3216.         StopRecordTime( end );
  3217.         GetBest( start, end, bestClocksGeneric );
  3218.     }
  3219.     PrintClocks( "generic->CreateTextureSpaceLightVectors()", COUNT, bestClocksGeneric );
  3220.  
  3221.     bestClocksSIMD = 0;
  3222.     for ( i = 0; i < NUMTESTS; i++ ) {
  3223.         StartRecordTime( start );
  3224.         p_simd->CreateTextureSpaceLightVectors( lightVectors2, lightOrigin, drawVerts, COUNT, indexes, COUNT*3 );
  3225.         StopRecordTime( end );
  3226.         GetBest( start, end, bestClocksSIMD );
  3227.     }
  3228.  
  3229.     for ( i = 0; i < COUNT; i++ ) {
  3230.         if ( !lightVectors1[i].Compare( lightVectors2[i], 1e-4f ) ) {
  3231.             break;
  3232.         }
  3233.     }
  3234.     result = ( i >= COUNT ) ? "ok" : S_COLOR_RED"X";
  3235.     PrintClocks( va( "   simd->CreateTextureSpaceLightVectors() %s", result ), COUNT, bestClocksSIMD, bestClocksGeneric );
  3236. }
  3237.  
  3238. /*
  3239. ============
  3240. TestGetSpecularTextureCoords
  3241. ============
  3242. */
  3243. void TestGetSpecularTextureCoords( void ) {
  3244.     int i, j;
  3245.     TIME_TYPE start, end, bestClocksGeneric, bestClocksSIMD;
  3246.     ALIGN16( idDrawVert drawVerts[COUNT]; )
  3247.     ALIGN16( idVec4 texCoords1[COUNT]; )
  3248.     ALIGN16( idVec4 texCoords2[COUNT]; )
  3249.     ALIGN16( int indexes[COUNT*3]; )
  3250.     ALIGN16( idVec3 lightVectors1[COUNT]; )
  3251.     ALIGN16( idVec3 lightVectors2[COUNT]; )
  3252.     idVec3 lightOrigin, viewOrigin;
  3253.     const char *result;
  3254.  
  3255.     idRandom srnd( RANDOM_SEED );
  3256.  
  3257.     for ( i = 0; i < COUNT; i++ ) {
  3258.         for ( j = 0; j < 3; j++ ) {
  3259.             drawVerts[i].xyz[j] = srnd.CRandomFloat() * 100.0f;
  3260.             drawVerts[i].normal[j] = srnd.CRandomFloat();
  3261.             drawVerts[i].tangents[0][j] = srnd.CRandomFloat();
  3262.             drawVerts[i].tangents[1][j] = srnd.CRandomFloat();
  3263.         }
  3264.     }
  3265.  
  3266.     for ( i = 0; i < COUNT; i++ ) {
  3267.         indexes[i*3+0] = ( i + 0 ) % COUNT;
  3268.         indexes[i*3+1] = ( i + 1 ) % COUNT;
  3269.         indexes[i*3+2] = ( i + 2 ) % COUNT;
  3270.     }
  3271.  
  3272.     lightOrigin[0] = srnd.CRandomFloat() * 100.0f;
  3273.     lightOrigin[1] = srnd.CRandomFloat() * 100.0f;
  3274.     lightOrigin[2] = srnd.CRandomFloat() * 100.0f;
  3275.     viewOrigin[0] = srnd.CRandomFloat() * 100.0f;
  3276.     viewOrigin[1] = srnd.CRandomFloat() * 100.0f;
  3277.     viewOrigin[2] = srnd.CRandomFloat() * 100.0f;
  3278.  
  3279.     bestClocksGeneric = 0;
  3280.     for ( i = 0; i < NUMTESTS; i++ ) {
  3281.         StartRecordTime( start );
  3282.         p_generic->CreateSpecularTextureCoords( texCoords1, lightOrigin, viewOrigin, drawVerts, COUNT, indexes, COUNT*3 );
  3283.         StopRecordTime( end );
  3284.         GetBest( start, end, bestClocksGeneric );
  3285.     }
  3286.     PrintClocks( "generic->CreateSpecularTextureCoords()", COUNT, bestClocksGeneric );
  3287.  
  3288.     bestClocksSIMD = 0;
  3289.     for ( i = 0; i < NUMTESTS; i++ ) {
  3290.         StartRecordTime( start );
  3291.         p_simd->CreateSpecularTextureCoords( texCoords2, lightOrigin, viewOrigin, drawVerts, COUNT, indexes, COUNT*3 );
  3292.         StopRecordTime( end );
  3293.         GetBest( start, end, bestClocksSIMD );
  3294.     }
  3295.  
  3296.     for ( i = 0; i < COUNT; i++ ) {
  3297.         if ( !texCoords1[i].Compare( texCoords2[i], 1e-2f ) ) {
  3298.             break;
  3299.         }
  3300.     }
  3301.     result = ( i >= COUNT ) ? "ok" : S_COLOR_RED"X";
  3302.     PrintClocks( va( "   simd->CreateSpecularTextureCoords() %s", result ), COUNT, bestClocksSIMD, bestClocksGeneric );
  3303. }
  3304.  
  3305. /*
  3306. ============
  3307. TestCreateShadowCache
  3308. ============
  3309. */
  3310. void TestCreateShadowCache( void ) {
  3311.     int i, j;
  3312.     TIME_TYPE start, end, bestClocksGeneric, bestClocksSIMD;
  3313.     ALIGN16( idDrawVert drawVerts[COUNT]; )
  3314.     ALIGN16( idVec4 vertexCache1[COUNT*2]; )
  3315.     ALIGN16( idVec4 vertexCache2[COUNT*2]; )
  3316.     ALIGN16( int originalVertRemap[COUNT]; )
  3317.     ALIGN16( int vertRemap1[COUNT]; )
  3318.     ALIGN16( int vertRemap2[COUNT]; )
  3319.     ALIGN16( idVec3 lightOrigin; )
  3320.     int numVerts1 = 0, numVerts2 = 0;
  3321.     const char *result;
  3322.  
  3323.     idRandom srnd( RANDOM_SEED );
  3324.  
  3325.     for ( i = 0; i < COUNT; i++ ) {
  3326.         for ( j = 0; j < 3; j++ ) {
  3327.             drawVerts[i].xyz[j] = srnd.CRandomFloat() * 100.0f;
  3328.         }
  3329.         originalVertRemap[i] = ( srnd.CRandomFloat() > 0.0f ) ? -1 : 0;
  3330.     }
  3331.     lightOrigin[0] = srnd.CRandomFloat() * 100.0f;
  3332.     lightOrigin[1] = srnd.CRandomFloat() * 100.0f;
  3333.     lightOrigin[2] = srnd.CRandomFloat() * 100.0f;
  3334.  
  3335.     bestClocksGeneric = 0;
  3336.     for ( i = 0; i < NUMTESTS; i++ ) {
  3337.         for ( j = 0; j < COUNT; j++ ) {
  3338.             vertRemap1[j] = originalVertRemap[j];
  3339.         }
  3340.         StartRecordTime( start );
  3341.         numVerts1 = p_generic->CreateShadowCache( vertexCache1, vertRemap1, lightOrigin, drawVerts, COUNT );
  3342.         StopRecordTime( end );
  3343.         GetBest( start, end, bestClocksGeneric );
  3344.     }
  3345.     PrintClocks( "generic->CreateShadowCache()", COUNT, bestClocksGeneric );
  3346.  
  3347.     bestClocksSIMD = 0;
  3348.     for ( i = 0; i < NUMTESTS; i++ ) {
  3349.         for ( j = 0; j < COUNT; j++ ) {
  3350.             vertRemap2[j] = originalVertRemap[j];
  3351.         }
  3352.         StartRecordTime( start );
  3353.         numVerts2 = p_simd->CreateShadowCache( vertexCache2, vertRemap2, lightOrigin, drawVerts, COUNT );
  3354.         StopRecordTime( end );
  3355.         GetBest( start, end, bestClocksSIMD );
  3356.     }
  3357.  
  3358.     for ( i = 0; i < COUNT; i++ ) {
  3359.         if ( i < ( numVerts1 / 2 ) ) {
  3360.             if ( !vertexCache1[i*2+0].Compare( vertexCache2[i*2+0], 1e-2f ) ) {
  3361.                 break;
  3362.             }
  3363.             if ( !vertexCache1[i*2+1].Compare( vertexCache2[i*2+1], 1e-2f ) ) {
  3364.                 break;
  3365.             }
  3366.         }
  3367.         if ( vertRemap1[i] != vertRemap2[i] ) {
  3368.             break;
  3369.         }
  3370.     }
  3371.  
  3372.     result = ( i >= COUNT && numVerts1 == numVerts2 ) ? "ok" : S_COLOR_RED"X";
  3373.     PrintClocks( va( "   simd->CreateShadowCache() %s", result ), COUNT, bestClocksSIMD, bestClocksGeneric );
  3374.  
  3375.     bestClocksGeneric = 0;
  3376.     for ( i = 0; i < NUMTESTS; i++ ) {
  3377.         StartRecordTime( start );
  3378.         p_generic->CreateVertexProgramShadowCache( vertexCache1, drawVerts, COUNT );
  3379.         StopRecordTime( end );
  3380.         GetBest( start, end, bestClocksGeneric );
  3381.     }
  3382.     PrintClocks( "generic->CreateVertexProgramShadowCache()", COUNT, bestClocksGeneric );
  3383.  
  3384.     bestClocksSIMD = 0;
  3385.     for ( i = 0; i < NUMTESTS; i++ ) {
  3386.         StartRecordTime( start );
  3387.         p_simd->CreateVertexProgramShadowCache( vertexCache2, drawVerts, COUNT );
  3388.         StopRecordTime( end );
  3389.         GetBest( start, end, bestClocksSIMD );
  3390.     }
  3391.  
  3392.     for ( i = 0; i < COUNT; i++ ) {
  3393.         if ( !vertexCache1[i*2+0].Compare( vertexCache2[i*2+0], 1e-2f ) ) {
  3394.             break;
  3395.         }
  3396.         if ( !vertexCache1[i*2+1].Compare( vertexCache2[i*2+1], 1e-2f ) ) {
  3397.             break;
  3398.         }
  3399.     }
  3400.     result = ( i >= COUNT ) ? "ok" : S_COLOR_RED"X";
  3401.     PrintClocks( va( "   simd->CreateVertexProgramShadowCache() %s", result ), COUNT, bestClocksSIMD, bestClocksGeneric );
  3402. }
  3403.  
  3404. #if 0 
  3405. #include "Simd_TestData.h"
  3406.  
  3407. /*
  3408. ============
  3409. TestShadowVolumes
  3410. ============
  3411. */
  3412. void TestShadowVolumes( void ) {
  3413.     int i;
  3414.     TIME_TYPE start, end, bestClocksGeneric, bestClocksSIMD;
  3415.     ALIGN16( int shadowIndexes1[8129]; )
  3416.     ALIGN16( int shadowIndexes2[8129]; )
  3417.     int numFacing1, numFacing2;
  3418.     const char *result;
  3419.  
  3420.     numFacing1 = numFacing2 = 0;
  3421.     bestClocksGeneric = 0;
  3422.     for ( i = 0; i < NUMTESTS; i++ ) {
  3423.         StartRecordTime( start );
  3424.         numFacing1 = p_generic->ShadowVolume_CountFacing( SIMD_testFacing, SIMD_numTestFacing );
  3425.         StopRecordTime( end );
  3426.         GetBest( start, end, bestClocksGeneric );
  3427.     }
  3428.     PrintClocks( "generic->ShadowVolume_CountFacing()", COUNT, bestClocksGeneric );
  3429.  
  3430.     bestClocksSIMD = 0;
  3431.     for ( i = 0; i < NUMTESTS; i++ ) {
  3432.         StartRecordTime( start );
  3433.         numFacing2 = p_simd->ShadowVolume_CountFacing( SIMD_testFacing, SIMD_numTestFacing );
  3434.         StopRecordTime( end );
  3435.         GetBest( start, end, bestClocksSIMD );
  3436.     }
  3437.  
  3438.     result = ( numFacing1 == numFacing2 ) ? "ok" : S_COLOR_RED"X";
  3439.     PrintClocks( va( "   simd->ShadowVolume_CountFacing() %s", result ), COUNT, bestClocksSIMD, bestClocksGeneric );
  3440.  
  3441.     bestClocksGeneric = 0;
  3442.     for ( i = 0; i < NUMTESTS; i++ ) {
  3443.         StartRecordTime( start );
  3444.         numFacing1 = p_generic->ShadowVolume_CountFacingCull( SIMD_testFacing, SIMD_numTestFacing, SIMD_testIndexes, SIMD_testCullBits );
  3445.         StopRecordTime( end );
  3446.         GetBest( start, end, bestClocksGeneric );
  3447.     }
  3448.     PrintClocks( "generic->ShadowVolume_CountFacing()", COUNT, bestClocksGeneric );
  3449.  
  3450.     bestClocksSIMD = 0;
  3451.     for ( i = 0; i < NUMTESTS; i++ ) {
  3452.         StartRecordTime( start );
  3453.         numFacing2 = p_simd->ShadowVolume_CountFacingCull( SIMD_testFacing, SIMD_numTestFacing, SIMD_testIndexes, SIMD_testCullBits );
  3454.         StopRecordTime( end );
  3455.         GetBest( start, end, bestClocksSIMD );
  3456.     }
  3457.  
  3458.     result = ( numFacing1 == numFacing2 ) ? "ok" : S_COLOR_RED"X";
  3459.     PrintClocks( va( "   simd->ShadowVolume_CountFacingCull() %s", result ), COUNT, bestClocksSIMD, bestClocksGeneric );
  3460.  
  3461.     bestClocksGeneric = 0;
  3462.     for ( i = 0; i < NUMTESTS; i++ ) {
  3463.         StartRecordTime( start );
  3464.         numFacing1 = p_generic->ShadowVolume_CreateSilTriangles( shadowIndexes1, SIMD_testFacing, ( const silEdge_s *)SIMD_testSilEdges, SIMD_numTestSilEdges );
  3465.         StopRecordTime( end );
  3466.         GetBest( start, end, bestClocksGeneric );
  3467.     }
  3468.     PrintClocks( "generic->ShadowVolume_CreateSilTriangles()", COUNT, bestClocksGeneric );
  3469.  
  3470.     bestClocksSIMD = 0;
  3471.     for ( i = 0; i < NUMTESTS; i++ ) {
  3472.         StartRecordTime( start );
  3473.         numFacing2 = p_simd->ShadowVolume_CreateSilTriangles( shadowIndexes2, SIMD_testFacing, ( const silEdge_s *)SIMD_testSilEdges, SIMD_numTestSilEdges );
  3474.         StopRecordTime( end );
  3475.         GetBest( start, end, bestClocksSIMD );
  3476.     }
  3477.  
  3478.     for ( i = 0; i < numFacing1; i++ ) {
  3479.         if ( shadowIndexes1[i] != shadowIndexes2[i] ) {
  3480.             break;
  3481.         }
  3482.     }
  3483.  
  3484.     result = ( i >= numFacing1 && numFacing1 == numFacing2 ) ? "ok" : S_COLOR_RED"X";
  3485.     PrintClocks( va( "   simd->ShadowVolume_CreateSilTriangles() %s", result ), COUNT, bestClocksSIMD, bestClocksGeneric );
  3486.  
  3487.     bestClocksGeneric = 0;
  3488.     for ( i = 0; i < NUMTESTS; i++ ) {
  3489.         StartRecordTime( start );
  3490.         numFacing1 = p_generic->ShadowVolume_CreateCapTriangles( shadowIndexes1, SIMD_testFacing, SIMD_testIndexes, SIMD_numTestIndexes );
  3491.         StopRecordTime( end );
  3492.         GetBest( start, end, bestClocksGeneric );
  3493.     }
  3494.     PrintClocks( "generic->ShadowVolume_CreateCapTriangles()", COUNT, bestClocksGeneric );
  3495.  
  3496.     bestClocksSIMD = 0;
  3497.     for ( i = 0; i < NUMTESTS; i++ ) {
  3498.         StartRecordTime( start );
  3499.         numFacing2 = p_simd->ShadowVolume_CreateCapTriangles( shadowIndexes2, SIMD_testFacing, SIMD_testIndexes, SIMD_numTestIndexes );
  3500.         StopRecordTime( end );
  3501.         GetBest( start, end, bestClocksSIMD );
  3502.     }
  3503.  
  3504.     for ( i = 0; i < numFacing1; i++ ) {
  3505.         if ( shadowIndexes1[i] != shadowIndexes2[i] ) {
  3506.             break;
  3507.         }
  3508.     }
  3509.  
  3510.     result = ( i >= numFacing1 && numFacing1 == numFacing2 ) ? "ok" : S_COLOR_RED"X";
  3511.     PrintClocks( va( "   simd->ShadowVolume_CreateCapTriangles() %s", result ), COUNT, bestClocksSIMD, bestClocksGeneric );
  3512. }
  3513. #endif
  3514.  
  3515. /*
  3516. ============
  3517. TestSoundUpSampling
  3518. ============
  3519. */
  3520. #define SOUND_UPSAMPLE_EPSILON        1.0f
  3521.  
  3522. void TestSoundUpSampling( void ) {
  3523.     int i;
  3524.     TIME_TYPE start, end, bestClocksGeneric, bestClocksSIMD;
  3525.     ALIGN16( short pcm[MIXBUFFER_SAMPLES*2]; )
  3526.     ALIGN16( float ogg0[MIXBUFFER_SAMPLES*2]; )
  3527.     ALIGN16( float ogg1[MIXBUFFER_SAMPLES*2]; )
  3528.     ALIGN16( float samples1[MIXBUFFER_SAMPLES*2]; )
  3529.     ALIGN16( float samples2[MIXBUFFER_SAMPLES*2]; )
  3530.     float *ogg[2];
  3531.     int kHz, numSpeakers;
  3532.     const char *result;
  3533.  
  3534.     idRandom srnd( RANDOM_SEED );
  3535.  
  3536.     for ( i = 0; i < MIXBUFFER_SAMPLES*2; i++ ) {
  3537.         pcm[i] = srnd.RandomInt( (1<<16) ) - (1<<15);
  3538.         ogg0[i] = srnd.RandomFloat();
  3539.         ogg1[i] = srnd.RandomFloat();
  3540.     }
  3541.  
  3542.     ogg[0] = ogg0;
  3543.     ogg[1] = ogg1;
  3544.  
  3545.     for ( numSpeakers = 1; numSpeakers <= 2; numSpeakers++ ) {
  3546.  
  3547.         for ( kHz = 11025; kHz <= 44100; kHz *= 2 ) {
  3548.             bestClocksGeneric = 0;
  3549.             for ( i = 0; i < NUMTESTS; i++ ) {
  3550.                 StartRecordTime( start );
  3551.                 p_generic->UpSamplePCMTo44kHz( samples1, pcm, MIXBUFFER_SAMPLES*numSpeakers*kHz/44100, kHz, numSpeakers );
  3552.                 StopRecordTime( end );
  3553.                 GetBest( start, end, bestClocksGeneric );
  3554.             }
  3555.             PrintClocks( va( "generic->UpSamplePCMTo44kHz( %d, %d )", kHz, numSpeakers ), MIXBUFFER_SAMPLES*numSpeakers*kHz/44100, bestClocksGeneric );
  3556.  
  3557.             bestClocksSIMD = 0;
  3558.             for ( i = 0; i < NUMTESTS; i++ ) {
  3559.                 StartRecordTime( start );
  3560.                 p_simd->UpSamplePCMTo44kHz( samples2, pcm, MIXBUFFER_SAMPLES*numSpeakers*kHz/44100, kHz, numSpeakers );
  3561.                 StopRecordTime( end );
  3562.                 GetBest( start, end, bestClocksSIMD );
  3563.             }
  3564.  
  3565.             for ( i = 0; i < MIXBUFFER_SAMPLES*numSpeakers; i++ ) {
  3566.                 if ( idMath::Fabs( samples1[i] - samples2[i] ) > SOUND_UPSAMPLE_EPSILON ) {
  3567.                     break;
  3568.                 }
  3569.             }
  3570.             result = ( i >= MIXBUFFER_SAMPLES*numSpeakers ) ? "ok" : S_COLOR_RED"X";
  3571.             PrintClocks( va( "   simd->UpSamplePCMTo44kHz( %d, %d ) %s", kHz, numSpeakers, result ), MIXBUFFER_SAMPLES*numSpeakers*kHz/44100, bestClocksSIMD, bestClocksGeneric );
  3572.         }
  3573.     }
  3574.  
  3575.     for ( numSpeakers = 1; numSpeakers <= 2; numSpeakers++ ) {
  3576.  
  3577.         for ( kHz = 11025; kHz <= 44100; kHz *= 2 ) {
  3578.             bestClocksGeneric = 0;
  3579.             for ( i = 0; i < NUMTESTS; i++ ) {
  3580.                 StartRecordTime( start );
  3581.                 p_generic->UpSampleOGGTo44kHz( samples1, ogg, MIXBUFFER_SAMPLES*numSpeakers*kHz/44100, kHz, numSpeakers );
  3582.                 StopRecordTime( end );
  3583.                 GetBest( start, end, bestClocksGeneric );
  3584.             }
  3585.             PrintClocks( va( "generic->UpSampleOGGTo44kHz( %d, %d )", kHz, numSpeakers ), MIXBUFFER_SAMPLES*numSpeakers*kHz/44100, bestClocksGeneric );
  3586.  
  3587.             bestClocksSIMD = 0;
  3588.             for ( i = 0; i < NUMTESTS; i++ ) {
  3589.                 StartRecordTime( start );
  3590.                 p_simd->UpSampleOGGTo44kHz( samples2, ogg, MIXBUFFER_SAMPLES*numSpeakers*kHz/44100, kHz, numSpeakers );
  3591.                 StopRecordTime( end );
  3592.                 GetBest( start, end, bestClocksSIMD );
  3593.             }
  3594.  
  3595.             for ( i = 0; i < MIXBUFFER_SAMPLES*numSpeakers; i++ ) {
  3596.                 if ( idMath::Fabs( samples1[i] - samples2[i] ) > SOUND_UPSAMPLE_EPSILON ) {
  3597.                     break;
  3598.                 }
  3599.             }
  3600.             result = ( i >= MIXBUFFER_SAMPLES ) ? "ok" : S_COLOR_RED"X";
  3601.             PrintClocks( va( "   simd->UpSampleOGGTo44kHz( %d, %d ) %s", kHz, numSpeakers, result ), MIXBUFFER_SAMPLES*numSpeakers*kHz/44100, bestClocksSIMD, bestClocksGeneric );
  3602.         }
  3603.     }
  3604. }
  3605.  
  3606. /*
  3607. ============
  3608. TestSoundMixing
  3609. ============
  3610. */
  3611. #define SOUND_MIX_EPSILON        2.0f
  3612.  
  3613. void TestSoundMixing( void ) {
  3614.     int i, j;
  3615.     TIME_TYPE start, end, bestClocksGeneric, bestClocksSIMD;
  3616.     ALIGN16( float origMixBuffer[MIXBUFFER_SAMPLES*6]; )
  3617.     ALIGN16( float mixBuffer1[MIXBUFFER_SAMPLES*6]; )
  3618.     ALIGN16( float mixBuffer2[MIXBUFFER_SAMPLES*6]; )
  3619.     ALIGN16( float samples[MIXBUFFER_SAMPLES*6]; )
  3620.     ALIGN16( short outSamples1[MIXBUFFER_SAMPLES*6]; )
  3621.     ALIGN16( short outSamples2[MIXBUFFER_SAMPLES*6]; )
  3622.     float lastV[6];
  3623.     float currentV[6];
  3624.     const char *result;
  3625.  
  3626.     idRandom srnd( RANDOM_SEED );
  3627.  
  3628.     for ( i = 0; i < 6; i++ ) {
  3629.         lastV[i] = srnd.CRandomFloat();
  3630.         currentV[i] = srnd.CRandomFloat();
  3631.     }
  3632.  
  3633.     for ( i = 0; i < MIXBUFFER_SAMPLES*6; i++ ) {
  3634.         origMixBuffer[i] = srnd.CRandomFloat();
  3635.         samples[i] = srnd.RandomInt( (1<<16) ) - (1<<15);
  3636.     }
  3637.  
  3638.     bestClocksGeneric = 0;
  3639.     for ( i = 0; i < NUMTESTS; i++ ) {
  3640.         for ( j = 0; j < MIXBUFFER_SAMPLES*6; j++ ) {
  3641.             mixBuffer1[j] = origMixBuffer[j];
  3642.         }
  3643.         StartRecordTime( start );
  3644.         p_generic->MixSoundTwoSpeakerMono( mixBuffer1, samples, MIXBUFFER_SAMPLES, lastV, currentV );
  3645.         StopRecordTime( end );
  3646.         GetBest( start, end, bestClocksGeneric );
  3647.     }
  3648.     PrintClocks( "generic->MixSoundTwoSpeakerMono()", MIXBUFFER_SAMPLES, bestClocksGeneric );
  3649.  
  3650.  
  3651.     bestClocksSIMD = 0;
  3652.     for ( i = 0; i < NUMTESTS; i++ ) {
  3653.         for ( j = 0; j < MIXBUFFER_SAMPLES*6; j++ ) {
  3654.             mixBuffer2[j] = origMixBuffer[j];
  3655.         }
  3656.         StartRecordTime( start );
  3657.         p_simd->MixSoundTwoSpeakerMono( mixBuffer2, samples, MIXBUFFER_SAMPLES, lastV, currentV );
  3658.         StopRecordTime( end );
  3659.         GetBest( start, end, bestClocksSIMD );
  3660.     }
  3661.  
  3662.     for ( i = 0; i < MIXBUFFER_SAMPLES*6; i++ ) {
  3663.         if ( idMath::Fabs( mixBuffer1[i] - mixBuffer2[i] ) > SOUND_MIX_EPSILON ) {
  3664.             break;
  3665.         }
  3666.     }
  3667.     result = ( i >= MIXBUFFER_SAMPLES*6 ) ? "ok" : S_COLOR_RED"X";
  3668.     PrintClocks( va( "   simd->MixSoundTwoSpeakerMono() %s", result ), MIXBUFFER_SAMPLES, bestClocksSIMD, bestClocksGeneric );
  3669.  
  3670.     bestClocksGeneric = 0;
  3671.     for ( i = 0; i < NUMTESTS; i++ ) {
  3672.         for ( j = 0; j < MIXBUFFER_SAMPLES*6; j++ ) {
  3673.             mixBuffer1[j] = origMixBuffer[j];
  3674.         }
  3675.         StartRecordTime( start );
  3676.         p_generic->MixSoundTwoSpeakerStereo( mixBuffer1, samples, MIXBUFFER_SAMPLES, lastV, currentV );
  3677.         StopRecordTime( end );
  3678.         GetBest( start, end, bestClocksGeneric );
  3679.     }
  3680.     PrintClocks( "generic->MixSoundTwoSpeakerStereo()", MIXBUFFER_SAMPLES, bestClocksGeneric );
  3681.  
  3682.  
  3683.     bestClocksSIMD = 0;
  3684.     for ( i = 0; i < NUMTESTS; i++ ) {
  3685.         for ( j = 0; j < MIXBUFFER_SAMPLES*6; j++ ) {
  3686.             mixBuffer2[j] = origMixBuffer[j];
  3687.         }
  3688.         StartRecordTime( start );
  3689.         p_simd->MixSoundTwoSpeakerStereo( mixBuffer2, samples, MIXBUFFER_SAMPLES, lastV, currentV );
  3690.         StopRecordTime( end );
  3691.         GetBest( start, end, bestClocksSIMD );
  3692.     }
  3693.  
  3694.     for ( i = 0; i < MIXBUFFER_SAMPLES*6; i++ ) {
  3695.         if ( idMath::Fabs( mixBuffer1[i] - mixBuffer2[i] ) > SOUND_MIX_EPSILON ) {
  3696.             break;
  3697.         }
  3698.     }
  3699.     result = ( i >= MIXBUFFER_SAMPLES*6 ) ? "ok" : S_COLOR_RED"X";
  3700.     PrintClocks( va( "   simd->MixSoundTwoSpeakerStereo() %s", result ), MIXBUFFER_SAMPLES, bestClocksSIMD, bestClocksGeneric );
  3701.  
  3702.  
  3703.     bestClocksGeneric = 0;
  3704.     for ( i = 0; i < NUMTESTS; i++ ) {
  3705.         for ( j = 0; j < MIXBUFFER_SAMPLES*6; j++ ) {
  3706.             mixBuffer1[j] = origMixBuffer[j];
  3707.         }
  3708.         StartRecordTime( start );
  3709.         p_generic->MixSoundSixSpeakerMono( mixBuffer1, samples, MIXBUFFER_SAMPLES, lastV, currentV );
  3710.         StopRecordTime( end );
  3711.         GetBest( start, end, bestClocksGeneric );
  3712.     }
  3713.     PrintClocks( "generic->MixSoundSixSpeakerMono()", MIXBUFFER_SAMPLES, bestClocksGeneric );
  3714.  
  3715.  
  3716.     bestClocksSIMD = 0;
  3717.     for ( i = 0; i < NUMTESTS; i++ ) {
  3718.         for ( j = 0; j < MIXBUFFER_SAMPLES*6; j++ ) {
  3719.             mixBuffer2[j] = origMixBuffer[j];
  3720.         }
  3721.         StartRecordTime( start );
  3722.         p_simd->MixSoundSixSpeakerMono( mixBuffer2, samples, MIXBUFFER_SAMPLES, lastV, currentV );
  3723.         StopRecordTime( end );
  3724.         GetBest( start, end, bestClocksSIMD );
  3725.     }
  3726.  
  3727.     for ( i = 0; i < MIXBUFFER_SAMPLES*6; i++ ) {
  3728.         if ( idMath::Fabs( mixBuffer1[i] - mixBuffer2[i] ) > SOUND_MIX_EPSILON ) {
  3729.             break;
  3730.         }
  3731.     }
  3732.     result = ( i >= MIXBUFFER_SAMPLES*6 ) ? "ok" : S_COLOR_RED"X";
  3733.     PrintClocks( va( "   simd->MixSoundSixSpeakerMono() %s", result ), MIXBUFFER_SAMPLES, bestClocksSIMD, bestClocksGeneric );
  3734.  
  3735.     bestClocksGeneric = 0;
  3736.     for ( i = 0; i < NUMTESTS; i++ ) {
  3737.         for ( j = 0; j < MIXBUFFER_SAMPLES*6; j++ ) {
  3738.             mixBuffer1[j] = origMixBuffer[j];
  3739.         }
  3740.         StartRecordTime( start );
  3741.         p_generic->MixSoundSixSpeakerStereo( mixBuffer1, samples, MIXBUFFER_SAMPLES, lastV, currentV );
  3742.         StopRecordTime( end );
  3743.         GetBest( start, end, bestClocksGeneric );
  3744.     }
  3745.     PrintClocks( "generic->MixSoundSixSpeakerStereo()", MIXBUFFER_SAMPLES, bestClocksGeneric );
  3746.  
  3747.  
  3748.     bestClocksSIMD = 0;
  3749.     for ( i = 0; i < NUMTESTS; i++ ) {
  3750.         for ( j = 0; j < MIXBUFFER_SAMPLES*6; j++ ) {
  3751.             mixBuffer2[j] = origMixBuffer[j];
  3752.         }
  3753.         StartRecordTime( start );
  3754.         p_simd->MixSoundSixSpeakerStereo( mixBuffer2, samples, MIXBUFFER_SAMPLES, lastV, currentV );
  3755.         StopRecordTime( end );
  3756.         GetBest( start, end, bestClocksSIMD );
  3757.     }
  3758.  
  3759.     for ( i = 0; i < MIXBUFFER_SAMPLES*6; i++ ) {
  3760.         if ( idMath::Fabs( mixBuffer1[i] - mixBuffer2[i] ) > SOUND_MIX_EPSILON ) {
  3761.             break;
  3762.         }
  3763.     }
  3764.     result = ( i >= MIXBUFFER_SAMPLES*6 ) ? "ok" : S_COLOR_RED"X";
  3765.     PrintClocks( va( "   simd->MixSoundSixSpeakerStereo() %s", result ), MIXBUFFER_SAMPLES, bestClocksSIMD, bestClocksGeneric );
  3766.  
  3767.  
  3768.     for ( i = 0; i < MIXBUFFER_SAMPLES*6; i++ ) {
  3769.         origMixBuffer[i] = srnd.RandomInt( (1<<17) ) - (1<<16);
  3770.     }
  3771.  
  3772.     bestClocksGeneric = 0;
  3773.     for ( i = 0; i < NUMTESTS; i++ ) {
  3774.         for ( j = 0; j < MIXBUFFER_SAMPLES*6; j++ ) {
  3775.             mixBuffer1[j] = origMixBuffer[j];
  3776.         }
  3777.         StartRecordTime( start );
  3778.         p_generic->MixedSoundToSamples( outSamples1, mixBuffer1, MIXBUFFER_SAMPLES*6 );
  3779.         StopRecordTime( end );
  3780.         GetBest( start, end, bestClocksGeneric );
  3781.     }
  3782.     PrintClocks( "generic->MixedSoundToSamples()", MIXBUFFER_SAMPLES, bestClocksGeneric );
  3783.  
  3784.     bestClocksSIMD = 0;
  3785.     for ( i = 0; i < NUMTESTS; i++ ) {
  3786.         for ( j = 0; j < MIXBUFFER_SAMPLES*6; j++ ) {
  3787.             mixBuffer2[j] = origMixBuffer[j];
  3788.         }
  3789.         StartRecordTime( start );
  3790.         p_simd->MixedSoundToSamples( outSamples2, mixBuffer2, MIXBUFFER_SAMPLES*6 );
  3791.         StopRecordTime( end );
  3792.         GetBest( start, end, bestClocksSIMD );
  3793.     }
  3794.  
  3795.     for ( i = 0; i < MIXBUFFER_SAMPLES*6; i++ ) {
  3796.         if ( outSamples1[i] != outSamples2[i] ) {
  3797.             break;
  3798.         }
  3799.     }
  3800.     result = ( i >= MIXBUFFER_SAMPLES*6 ) ? "ok" : S_COLOR_RED"X";
  3801.     PrintClocks( va( "   simd->MixedSoundToSamples() %s", result ), MIXBUFFER_SAMPLES, bestClocksSIMD, bestClocksGeneric );
  3802. }
  3803.  
  3804. /*
  3805. ============
  3806. TestMath
  3807. ============
  3808. */
  3809. void TestMath( void ) {
  3810.     int i;
  3811.     TIME_TYPE start, end, bestClocks;
  3812.  
  3813.     idLib::common->Printf("====================================\n" );
  3814.  
  3815.     float tst = -1.0f;
  3816.     float tst2 = 1.0f;
  3817.     float testvar = 1.0f;
  3818.     idRandom rnd;
  3819.  
  3820.     bestClocks = 0;
  3821.     tst = rnd.CRandomFloat();
  3822.     for ( i = 0; i < NUMTESTS; i++ ) {
  3823.         StartRecordTime( start );
  3824.         tst = fabs( tst );
  3825.         StopRecordTime( end );
  3826.         GetBest( start, end, bestClocks );
  3827.         testvar = ( testvar + tst ) * tst;
  3828.         tst = rnd.CRandomFloat();
  3829.     }
  3830.     PrintClocks( "            fabs( tst )", 1, bestClocks );
  3831.  
  3832.     bestClocks = 0;
  3833.     tst = rnd.CRandomFloat();
  3834.     for ( i = 0; i < NUMTESTS; i++ ) {
  3835.         StartRecordTime( start );
  3836.         int tmp = * ( int * ) &tst;
  3837.         tmp &= 0x7FFFFFFF;
  3838.         tst = * ( float * ) &tmp;
  3839.         StopRecordTime( end );
  3840.         GetBest( start, end, bestClocks );
  3841.         testvar = ( testvar + tst ) * tst;
  3842.         tst = rnd.CRandomFloat();
  3843.     }
  3844.     PrintClocks( "    idMath::Fabs( tst )", 1, bestClocks );
  3845.  
  3846.     bestClocks = 0;
  3847.     tst = 10.0f + 100.0f * rnd.RandomFloat();
  3848.     for ( i = 0; i < NUMTESTS; i++ ) {
  3849.         StartRecordTime( start );
  3850.         tst = sqrt( tst );
  3851.         StopRecordTime( end );
  3852.         GetBest( start, end, bestClocks );
  3853.         testvar = ( testvar + tst ) * tst * 0.01f;
  3854.         tst = 10.0f + 100.0f * rnd.RandomFloat();
  3855.     }
  3856.     PrintClocks( "            sqrt( tst )", 1, bestClocks );
  3857.  
  3858.     bestClocks = 0;
  3859.     tst = rnd.RandomFloat();
  3860.     for ( i = 0; i < NUMTESTS; i++ ) {
  3861.         StartRecordTime( start );
  3862.         tst = idMath::Sqrt( tst );
  3863.         StopRecordTime( end );
  3864.         GetBest( start, end, bestClocks );
  3865.         testvar = ( testvar + tst ) * tst;
  3866.         tst = rnd.RandomFloat();
  3867.     }
  3868.     PrintClocks( "    idMath::Sqrt( tst )", 1, bestClocks );
  3869.  
  3870.     bestClocks = 0;
  3871.     tst = rnd.RandomFloat();
  3872.     for ( i = 0; i < NUMTESTS; i++ ) {
  3873.         StartRecordTime( start );
  3874.         tst = idMath::Sqrt16( tst );
  3875.         StopRecordTime( end );
  3876.         GetBest( start, end, bestClocks );
  3877.         testvar = ( testvar + tst ) * tst;
  3878.         tst = rnd.RandomFloat();
  3879.     }
  3880.     PrintClocks( "  idMath::Sqrt16( tst )", 1, bestClocks );
  3881.  
  3882.     bestClocks = 0;
  3883.     tst = rnd.RandomFloat();
  3884.     for ( i = 0; i < NUMTESTS; i++ ) {
  3885.         StartRecordTime( start );
  3886.         tst = idMath::Sqrt64( tst );
  3887.         StopRecordTime( end );
  3888.         GetBest( start, end, bestClocks );
  3889.         testvar = ( testvar + tst ) * tst;
  3890.         tst = rnd.RandomFloat();
  3891.     }
  3892.     PrintClocks( "  idMath::Sqrt64( tst )", 1, bestClocks );
  3893.  
  3894.     bestClocks = 0;
  3895.     tst = rnd.RandomFloat();
  3896.     for ( i = 0; i < NUMTESTS; i++ ) {
  3897.         StartRecordTime( start );
  3898.         tst = tst * idMath::RSqrt( tst );
  3899.         StopRecordTime( end );
  3900.         GetBest( start, end, bestClocks );
  3901.         testvar = ( testvar + tst ) * tst;
  3902.         tst = rnd.RandomFloat();
  3903.     }
  3904.     PrintClocks( "   idMath::RSqrt( tst )", 1, bestClocks );
  3905.  
  3906.     bestClocks = 0;
  3907.     tst = rnd.CRandomFloat();
  3908.     for ( i = 0; i < NUMTESTS; i++ ) {
  3909.         StartRecordTime( start );
  3910.         tst = idMath::Sin( tst );
  3911.         StopRecordTime( end );
  3912.         GetBest( start, end, bestClocks );
  3913.         testvar = ( testvar + tst ) * tst;
  3914.         tst = rnd.CRandomFloat();
  3915.     }
  3916.     PrintClocks( "     idMath::Sin( tst )", 1, bestClocks );
  3917.  
  3918.     bestClocks = 0;
  3919.     tst = rnd.CRandomFloat();
  3920.     for ( i = 0; i < NUMTESTS; i++ ) {
  3921.         StartRecordTime( start );
  3922.         tst = idMath::Sin16( tst );
  3923.         StopRecordTime( end );
  3924.         GetBest( start, end, bestClocks );
  3925.         testvar = ( testvar + tst ) * tst;
  3926.         tst = rnd.CRandomFloat();
  3927.     }
  3928.     PrintClocks( "   idMath::Sin16( tst )", 1, bestClocks );
  3929.  
  3930.     bestClocks = 0;
  3931.     tst = rnd.CRandomFloat();
  3932.     for ( i = 0; i < NUMTESTS; i++ ) {
  3933.         StartRecordTime( start );
  3934.         tst = idMath::Cos( tst );
  3935.         StopRecordTime( end );
  3936.         GetBest( start, end, bestClocks );
  3937.         testvar = ( testvar + tst ) * tst;
  3938.         tst = rnd.CRandomFloat();
  3939.     }
  3940.     PrintClocks( "     idMath::Cos( tst )", 1, bestClocks );
  3941.  
  3942.     bestClocks = 0;
  3943.     tst = rnd.CRandomFloat();
  3944.     for ( i = 0; i < NUMTESTS; i++ ) {
  3945.         StartRecordTime( start );
  3946.         tst = idMath::Cos16( tst );
  3947.         StopRecordTime( end );
  3948.         GetBest( start, end, bestClocks );
  3949.         testvar = ( testvar + tst ) * tst;
  3950.         tst = rnd.CRandomFloat();
  3951.     }
  3952.     PrintClocks( "   idMath::Cos16( tst )", 1, bestClocks );
  3953.  
  3954.     bestClocks = 0;
  3955.     tst = rnd.CRandomFloat();
  3956.     for ( i = 0; i < NUMTESTS; i++ ) {
  3957.         StartRecordTime( start );
  3958.         idMath::SinCos( tst, tst, tst2 );
  3959.         StopRecordTime( end );
  3960.         GetBest( start, end, bestClocks );
  3961.         testvar = ( testvar + tst ) * tst;
  3962.         tst = rnd.CRandomFloat();
  3963.     }
  3964.     PrintClocks( "  idMath::SinCos( tst )", 1, bestClocks );
  3965.  
  3966.     bestClocks = 0;
  3967.     tst = rnd.CRandomFloat();
  3968.     for ( i = 0; i < NUMTESTS; i++ ) {
  3969.         StartRecordTime( start );
  3970.         idMath::SinCos16( tst, tst, tst2 );
  3971.         StopRecordTime( end );
  3972.         GetBest( start, end, bestClocks );
  3973.         testvar = ( testvar + tst ) * tst;
  3974.         tst = rnd.CRandomFloat();
  3975.     }
  3976.     PrintClocks( "idMath::SinCos16( tst )", 1, bestClocks );
  3977.  
  3978.     bestClocks = 0;
  3979.     tst = rnd.CRandomFloat();
  3980.     for ( i = 0; i < NUMTESTS; i++ ) {
  3981.         StartRecordTime( start );
  3982.         tst = idMath::Tan( tst );
  3983.         StopRecordTime( end );
  3984.         GetBest( start, end, bestClocks );
  3985.         testvar = ( testvar + tst ) * tst;
  3986.         tst = rnd.CRandomFloat();
  3987.     }
  3988.     PrintClocks( "     idMath::Tan( tst )", 1, bestClocks );
  3989.  
  3990.     bestClocks = 0;
  3991.     tst = rnd.CRandomFloat();
  3992.     for ( i = 0; i < NUMTESTS; i++ ) {
  3993.         StartRecordTime( start );
  3994.         tst = idMath::Tan16( tst );
  3995.         StopRecordTime( end );
  3996.         GetBest( start, end, bestClocks );
  3997.         testvar = ( testvar + tst ) * tst;
  3998.         tst = rnd.CRandomFloat();
  3999.     }
  4000.     PrintClocks( "   idMath::Tan16( tst )", 1, bestClocks );
  4001.  
  4002.     bestClocks = 0;
  4003.     tst = rnd.CRandomFloat();
  4004.     for ( i = 0; i < NUMTESTS; i++ ) {
  4005.         StartRecordTime( start );
  4006.         tst = idMath::ASin( tst );
  4007.         StopRecordTime( end );
  4008.         GetBest( start, end, bestClocks );
  4009.         testvar = ( testvar + tst ) * tst * ( 1.0f / idMath::PI );
  4010.         tst = rnd.CRandomFloat();
  4011.     }
  4012.     PrintClocks( "    idMath::ASin( tst )", 1, bestClocks );
  4013.  
  4014.     bestClocks = 0;
  4015.     tst = rnd.CRandomFloat();
  4016.     for ( i = 0; i < NUMTESTS; i++ ) {
  4017.         StartRecordTime( start );
  4018.         tst = idMath::ASin16( tst );
  4019.         StopRecordTime( end );
  4020.         GetBest( start, end, bestClocks );
  4021.         testvar = ( testvar + tst ) * tst * ( 1.0f / idMath::PI );
  4022.         tst = rnd.CRandomFloat();
  4023.     }
  4024.     PrintClocks( "  idMath::ASin16( tst )", 1, bestClocks );
  4025.  
  4026.     bestClocks = 0;
  4027.     tst = rnd.CRandomFloat();
  4028.     for ( i = 0; i < NUMTESTS; i++ ) {
  4029.         StartRecordTime( start );
  4030.         tst = idMath::ACos( tst );
  4031.         StopRecordTime( end );
  4032.         GetBest( start, end, bestClocks );
  4033.         testvar = ( testvar + tst ) * tst * ( 1.0f / idMath::PI );
  4034.         tst = rnd.CRandomFloat();
  4035.     }
  4036.     PrintClocks( "    idMath::ACos( tst )", 1, bestClocks );
  4037.  
  4038.     bestClocks = 0;
  4039.     tst = rnd.CRandomFloat();
  4040.     for ( i = 0; i < NUMTESTS; i++ ) {
  4041.         StartRecordTime( start );
  4042.         tst = idMath::ACos16( tst );
  4043.         StopRecordTime( end );
  4044.         GetBest( start, end, bestClocks );
  4045.         testvar = ( testvar + tst ) * tst * ( 1.0f / idMath::PI );
  4046.         tst = rnd.CRandomFloat();
  4047.     }
  4048.     PrintClocks( "  idMath::ACos16( tst )", 1, bestClocks );
  4049.  
  4050.     bestClocks = 0;
  4051.     tst = rnd.CRandomFloat();
  4052.     for ( i = 0; i < NUMTESTS; i++ ) {
  4053.         StartRecordTime( start );
  4054.         tst = idMath::ATan( tst );
  4055.         StopRecordTime( end );
  4056.         GetBest( start, end, bestClocks );
  4057.         testvar = ( testvar + tst ) * tst;
  4058.         tst = rnd.CRandomFloat();
  4059.     }
  4060.     PrintClocks( "    idMath::ATan( tst )", 1, bestClocks );
  4061.  
  4062.     bestClocks = 0;
  4063.     tst = rnd.CRandomFloat();
  4064.     for ( i = 0; i < NUMTESTS; i++ ) {
  4065.         StartRecordTime( start );
  4066.         tst = idMath::ATan16( tst );
  4067.         StopRecordTime( end );
  4068.         GetBest( start, end, bestClocks );
  4069.         testvar = ( testvar + tst ) * tst;
  4070.         tst = rnd.CRandomFloat();
  4071.     }
  4072.     PrintClocks( "  idMath::ATan16( tst )", 1, bestClocks );
  4073.  
  4074.     bestClocks = 0;
  4075.     tst = rnd.CRandomFloat();
  4076.     for ( i = 0; i < NUMTESTS; i++ ) {
  4077.         StartRecordTime( start );
  4078.         tst = idMath::Pow( 2.7f, tst );
  4079.         StopRecordTime( end );
  4080.         GetBest( start, end, bestClocks );
  4081.         testvar = ( testvar + tst ) * tst * 0.1f;
  4082.         tst = rnd.CRandomFloat();
  4083.     }
  4084.     PrintClocks( "    idMath::Pow( tst )", 1, bestClocks );
  4085.  
  4086.     bestClocks = 0;
  4087.     tst = rnd.CRandomFloat();
  4088.     for ( i = 0; i < NUMTESTS; i++ ) {
  4089.         StartRecordTime( start );
  4090.         tst = idMath::Pow16( 2.7f, tst );
  4091.         StopRecordTime( end );
  4092.         GetBest( start, end, bestClocks );
  4093.         testvar = ( testvar + tst ) * tst * 0.1f;
  4094.         tst = rnd.CRandomFloat();
  4095.     }
  4096.     PrintClocks( "  idMath::Pow16( tst )", 1, bestClocks );
  4097.  
  4098.     bestClocks = 0;
  4099.     tst = rnd.CRandomFloat();
  4100.     for ( i = 0; i < NUMTESTS; i++ ) {
  4101.         StartRecordTime( start );
  4102.         tst = idMath::Exp( tst );
  4103.         StopRecordTime( end );
  4104.         GetBest( start, end, bestClocks );
  4105.         testvar = ( testvar + tst ) * tst * 0.1f;
  4106.         tst = rnd.CRandomFloat();
  4107.     }
  4108.     PrintClocks( "    idMath::Exp( tst )", 1, bestClocks );
  4109.  
  4110.     bestClocks = 0;
  4111.     tst = rnd.CRandomFloat();
  4112.     for ( i = 0; i < NUMTESTS; i++ ) {
  4113.         StartRecordTime( start );
  4114.         tst = idMath::Exp16( tst );
  4115.         StopRecordTime( end );
  4116.         GetBest( start, end, bestClocks );
  4117.         testvar = ( testvar + tst ) * tst * 0.1f;
  4118.         tst = rnd.CRandomFloat();
  4119.     }
  4120.     PrintClocks( "  idMath::Exp16( tst )", 1, bestClocks );
  4121.  
  4122.     bestClocks = 0;
  4123.     tst = rnd.CRandomFloat();
  4124.     for ( i = 0; i < NUMTESTS; i++ ) {
  4125.         tst = fabs( tst ) + 1.0f;
  4126.         StartRecordTime( start );
  4127.         tst = idMath::Log( tst );
  4128.         StopRecordTime( end );
  4129.         GetBest( start, end, bestClocks );
  4130.         testvar = ( testvar + tst ) * tst;
  4131.         tst = rnd.CRandomFloat();
  4132.     }
  4133.     PrintClocks( "    idMath::Log( tst )", 1, bestClocks );
  4134.  
  4135.     bestClocks = 0;
  4136.     tst = rnd.CRandomFloat();
  4137.     for ( i = 0; i < NUMTESTS; i++ ) {
  4138.         tst = fabs( tst ) + 1.0f;
  4139.         StartRecordTime( start );
  4140.         tst = idMath::Log16( tst );
  4141.         StopRecordTime( end );
  4142.         GetBest( start, end, bestClocks );
  4143.         testvar = ( testvar + tst ) * tst;
  4144.         tst = rnd.CRandomFloat();
  4145.     }
  4146.     PrintClocks( "  idMath::Log16( tst )", 1, bestClocks );
  4147.  
  4148.     idLib::common->Printf( "testvar = %f\n", testvar );
  4149.  
  4150.     idMat3 resultMat3;
  4151.     idQuat fromQuat, toQuat, resultQuat;
  4152.     idCQuat cq;
  4153.     idAngles ang;
  4154.  
  4155.     fromQuat = idAngles( 30, 45, 0 ).ToQuat();
  4156.     toQuat = idAngles( 45, 0, 0 ).ToQuat();
  4157.     cq = idAngles( 30, 45, 0 ).ToQuat().ToCQuat();
  4158.     ang = idAngles( 30, 40, 50 );
  4159.  
  4160.     bestClocks = 0;
  4161.     for ( i = 0; i < NUMTESTS; i++ ) {
  4162.         StartRecordTime( start );
  4163.         resultMat3 = fromQuat.ToMat3();
  4164.         StopRecordTime( end );
  4165.         GetBest( start, end, bestClocks );
  4166.     }
  4167.     PrintClocks( "       idQuat::ToMat3()", 1, bestClocks );
  4168.  
  4169.     bestClocks = 0;
  4170.     for ( i = 0; i < NUMTESTS; i++ ) {
  4171.         StartRecordTime( start );
  4172.         resultQuat.Slerp( fromQuat, toQuat, 0.3f );
  4173.         StopRecordTime( end );
  4174.         GetBest( start, end, bestClocks );
  4175.     }
  4176.     PrintClocks( "        idQuat::Slerp()", 1, bestClocks );
  4177.  
  4178.     bestClocks = 0;
  4179.     for ( i = 0; i < NUMTESTS; i++ ) {
  4180.         StartRecordTime( start );
  4181.         resultQuat = cq.ToQuat();
  4182.         StopRecordTime( end );
  4183.         GetBest( start, end, bestClocks );
  4184.     }
  4185.     PrintClocks( "      idCQuat::ToQuat()", 1, bestClocks );
  4186.  
  4187.     bestClocks = 0;
  4188.     for ( i = 0; i < NUMTESTS; i++ ) {
  4189.         StartRecordTime( start );
  4190.         resultQuat = ang.ToQuat();
  4191.         StopRecordTime( end );
  4192.         GetBest( start, end, bestClocks );
  4193.     }
  4194.     PrintClocks( "     idAngles::ToQuat()", 1, bestClocks );
  4195.  
  4196.     bestClocks = 0;
  4197.     for ( i = 0; i < NUMTESTS; i++ ) {
  4198.         StartRecordTime( start );
  4199.         resultMat3 = ang.ToMat3();
  4200.         StopRecordTime( end );
  4201.         GetBest( start, end, bestClocks );
  4202.     }
  4203.     PrintClocks( "     idAngles::ToMat3()", 1, bestClocks );
  4204. }
  4205.  
  4206. /*
  4207. ============
  4208. idSIMD::Test_f
  4209. ============
  4210. */
  4211. void idSIMD::Test_f( const idCmdArgs &args ) {
  4212. // RAVEN BEGIN
  4213. // jsinger: at the moment this doesn't compile on xenon, but we also shouldn't need it anyway
  4214. #ifndef _XENON
  4215. #ifdef _WINDOWS
  4216.     SetThreadPriority( GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL );
  4217. #endif // _WINDOWS
  4218.  
  4219.     p_simd = processor;
  4220.     p_generic = generic;
  4221.  
  4222.     if ( idStr::Length( args.Argv( 1 ) ) != 0 ) {
  4223.         cpuid_t cpuid = idLib::sys->GetProcessorId();
  4224.         idStr argString = args.Args();
  4225.  
  4226.         argString.Replace( " ", "" );
  4227.  
  4228. #ifdef _WINDOWS
  4229.         if ( idStr::Icmp( argString, "MMX" ) == 0 ) {
  4230.             if ( !( cpuid & CPUID_MMX ) ) {
  4231.                 common->Printf( "CPU does not support MMX\n" );
  4232.                 return;
  4233.             }
  4234.             p_simd = new idSIMD_MMX;
  4235.         } else if ( idStr::Icmp( argString, "3DNow" ) == 0 ) {
  4236.             if ( !( cpuid & CPUID_MMX ) || !( cpuid & CPUID_3DNOW ) ) {
  4237.                 common->Printf( "CPU does not support MMX & 3DNow\n" );
  4238.                 return;
  4239.             }
  4240.             p_simd = new idSIMD_3DNow;
  4241.         } else if ( idStr::Icmp( argString, "SSE" ) == 0 ) {
  4242.             if ( !( cpuid & CPUID_MMX ) || !( cpuid & CPUID_SSE ) ) {
  4243.                 common->Printf( "CPU does not support MMX & SSE\n" );
  4244.                 return;
  4245.             }
  4246.             p_simd = new idSIMD_SSE;
  4247.         } else if ( idStr::Icmp( argString, "SSE2" ) == 0 ) {
  4248.             if ( !( cpuid & CPUID_MMX ) || !( cpuid & CPUID_SSE ) || !( cpuid & CPUID_SSE2 ) ) {
  4249.                 common->Printf( "CPU does not support MMX & SSE & SSE2\n" );
  4250.                 return;
  4251.             }
  4252.             p_simd = new idSIMD_SSE2;
  4253.         } else if ( idStr::Icmp( argString, "SSE3" ) == 0 ) {
  4254.             if ( !( cpuid & CPUID_MMX ) || !( cpuid & CPUID_SSE ) || !( cpuid & CPUID_SSE2 ) || !( cpuid & CPUID_SSE3 ) ) {
  4255.                 common->Printf( "CPU does not support MMX & SSE & SSE2 & SSE3\n" );
  4256.                 return;
  4257.             }
  4258.             p_simd = new idSIMD_SSE3();
  4259.         } else 
  4260. #endif // _WINDOWS
  4261.             if ( idStr::Icmp( argString, "AltiVec" ) == 0 ) {
  4262.             if ( !( cpuid & CPUID_ALTIVEC ) ) {
  4263.                 common->Printf( "CPU does not support AltiVec\n" );
  4264.                 return;
  4265.             }
  4266. #ifdef MACOS_X
  4267.             p_simd = new idSIMD_AltiVec();
  4268. #endif
  4269.         } else {
  4270.             common->Printf( "invalid argument, use: MMX, 3DNow, SSE, SSE2, SSE3, AltiVec\n" );
  4271.             return;
  4272.         }
  4273.     }
  4274.  
  4275.     idLib::common->SetRefreshOnPrint( true );
  4276.  
  4277.     idLib::common->Printf( "using %s for SIMD processing\n", p_simd->GetName() );
  4278.  
  4279.     GetBaseClocks();
  4280. /*
  4281.     TestMath();
  4282.     TestAdd();
  4283.     TestSub();
  4284.     TestMul();
  4285.     TestDiv();
  4286.     TestMulAdd();
  4287.     TestMulSub();
  4288.     TestDot();
  4289.     TestCompare();
  4290.     TestMinMax();
  4291.     TestClamp();
  4292.     TestMemcpy();
  4293.     TestMemset();
  4294.  
  4295.     TestMatXMultiplyVecX();
  4296.     TestMatXMultiplyAddVecX();
  4297.     TestMatXTransposeMultiplyVecX();
  4298.     TestMatXTransposeMultiplyAddVecX();
  4299.     TestMatXMultiplyMatX();
  4300.     TestMatXTransposeMultiplyMatX();
  4301.     TestMatXLowerTriangularSolve();
  4302.     TestMatXLowerTriangularSolveTranspose();
  4303.     TestMatXLDLTFactor();
  4304.  
  4305.     idLib::common->Printf("====================================\n" );
  4306. */
  4307.     TestBlendJoints();
  4308.     TestConvertJointQuatsToJointMats();
  4309.     TestConvertJointMatsToJointQuats();
  4310.     TestTransformJoints();
  4311.     TestUntransformJoints();
  4312.     TestTransformVertsNew();
  4313. /*    TestTracePointCull();
  4314.     TestDecalPointCull();
  4315.     TestOverlayPointCull();
  4316.     TestDeriveTriPlanes();
  4317.     TestDeriveTangents();
  4318.     TestDeriveUnsmoothedTangents();
  4319.     TestNormalizeTangents();
  4320.     TestGetTextureSpaceLightVectors();
  4321.     TestGetSpecularTextureCoords();
  4322.     TestCreateShadowCache();
  4323.  
  4324.     idLib::common->Printf("====================================\n" );
  4325.  
  4326.     TestSoundUpSampling();
  4327.     TestSoundMixing();
  4328. */
  4329.     idLib::common->SetRefreshOnPrint( false );
  4330.  
  4331.     if ( p_simd != processor ) {
  4332.         delete p_simd;
  4333.     }
  4334.     p_simd = NULL;
  4335.     p_generic = NULL;
  4336.  
  4337. #ifdef _WINDOWS
  4338.     SetThreadPriority( GetCurrentThread(), THREAD_PRIORITY_NORMAL );
  4339. #endif // _WINDOWS
  4340. #endif
  4341. // RAVEN END
  4342. }
  4343.