Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

113 lines
2.4 KiB

  1. //========= Copyright � 1996-2006, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: generates 4 randum numbers in the range 0..1 quickly, using SIMD
  4. //
  5. //=====================================================================================//
  6. #include <math.h>
  7. #include <float.h> // needed for flt_epsilon
  8. #include "basetypes.h"
  9. #ifndef _PS3
  10. #include <memory.h>
  11. #endif
  12. #include "tier0/dbg.h"
  13. #include "mathlib/mathlib.h"
  14. #include "mathlib/vector.h"
  15. #include "mathlib/ssemath.h"
  16. // memdbgon must be the last include file in a .cpp file!!!
  17. #include "tier0/memdbgon.h"
  18. // see knuth volume 3 for insight.
  19. class SIMDRandStreamContext
  20. {
  21. fltx4 m_RandY[55];
  22. fltx4 *m_pRand_J, *m_pRand_K;
  23. public:
  24. void Seed( uint32 seed )
  25. {
  26. m_pRand_J=m_RandY+23; m_pRand_K=m_RandY+54;
  27. for(int i=0;i<55;i++)
  28. {
  29. for(int j=0;j<4;j++)
  30. {
  31. SubFloat( m_RandY[i], j) = (seed>>16)/65536.0;
  32. seed=(seed+1)*3141592621u;
  33. }
  34. }
  35. }
  36. inline fltx4 RandSIMD( void )
  37. {
  38. // ret= rand[k]+rand[j]
  39. fltx4 retval=AddSIMD( *m_pRand_K, *m_pRand_J );
  40. // if ( ret>=1.0) ret-=1.0
  41. bi32x4 overflow_mask=CmpGeSIMD( retval, Four_Ones );
  42. retval=SubSIMD( retval, AndSIMD( Four_Ones, overflow_mask ) );
  43. *m_pRand_K = retval;
  44. // update pointers w/ wrap-around
  45. if ( --m_pRand_J < m_RandY )
  46. m_pRand_J=m_RandY+54;
  47. if ( --m_pRand_K < m_RandY )
  48. m_pRand_K=m_RandY+54;
  49. return retval;
  50. }
  51. };
  52. #define MAX_SIMULTANEOUS_RANDOM_STREAMS 32
  53. static SIMDRandStreamContext s_SIMDRandContexts[MAX_SIMULTANEOUS_RANDOM_STREAMS];
  54. static volatile int s_nRandContextsInUse[MAX_SIMULTANEOUS_RANDOM_STREAMS];
  55. void SeedRandSIMD(uint32 seed)
  56. {
  57. for( int i = 0; i<MAX_SIMULTANEOUS_RANDOM_STREAMS; i++)
  58. s_SIMDRandContexts[i].Seed( seed+i );
  59. }
  60. fltx4 RandSIMD( int nContextIndex )
  61. {
  62. return s_SIMDRandContexts[nContextIndex].RandSIMD();
  63. }
  64. int GetSIMDRandContext( void )
  65. {
  66. for(;;)
  67. {
  68. for(int i=0; i < NELEMS( s_SIMDRandContexts ); i++)
  69. {
  70. if ( ! s_nRandContextsInUse[i] ) // available?
  71. {
  72. // try to take it!
  73. if ( ThreadInterlockedAssignIf( &( s_nRandContextsInUse[i]), 1, 0 ) )
  74. {
  75. ThreadMemoryBarrier();
  76. return i; // done!
  77. }
  78. }
  79. }
  80. Assert(0); // why don't we have enough buffers?
  81. ThreadSleep();
  82. }
  83. }
  84. void ReleaseSIMDRandContext( int nContext )
  85. {
  86. ThreadMemoryBarrier();
  87. s_nRandContextsInUse[ nContext ] = 0;
  88. }
  89. fltx4 RandSIMD( void )
  90. {
  91. return s_SIMDRandContexts[0].RandSIMD();
  92. }