Team Fortress 2 Source Code as on 22/4/2020
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.

109 lines
2.3 KiB

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