WasmMath.inl 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft Corporation and contributors. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. #pragma once
  6. namespace Wasm
  7. {
  8. const uint64 specialDivLeftValue = (uint64)1 << 63;
  9. template<>
  10. inline int64 WasmMath::Rem( int64 aLeft, int64 aRight )
  11. {
  12. return (aLeft == specialDivLeftValue && aRight == -1) ? 0 : aLeft % aRight;
  13. }
  14. template<>
  15. inline uint64 WasmMath::Rem( uint64 aLeft, uint64 aRight )
  16. {
  17. return (aLeft == specialDivLeftValue && aRight == -1) ? specialDivLeftValue : aLeft % aRight;
  18. }
  19. template<typename T>
  20. inline T WasmMath::Shl( T aLeft, T aRight )
  21. {
  22. return aLeft << (aRight & (sizeof(T)*8-1));
  23. }
  24. template<typename T>
  25. inline T WasmMath::Shr( T aLeft, T aRight )
  26. {
  27. return aLeft >> (aRight & (sizeof(T)*8-1));
  28. }
  29. template<typename T>
  30. inline T WasmMath::ShrU( T aLeft, T aRight )
  31. {
  32. return aLeft >> (aRight & (sizeof(T)*8-1));
  33. }
  34. template<>
  35. inline int WasmMath::Ctz(int value)
  36. {
  37. DWORD index;
  38. if (_BitScanForward(&index, value))
  39. {
  40. return index;
  41. }
  42. return 32;
  43. }
  44. template<>
  45. inline int64 WasmMath::Ctz(int64 value)
  46. {
  47. DWORD index;
  48. #if TARGET_64
  49. if (_BitScanForward64(&index, value))
  50. {
  51. return index;
  52. }
  53. #else
  54. if (_BitScanForward(&index, (int32)value))
  55. {
  56. return index;
  57. }
  58. if (_BitScanForward(&index, (int32)(value >> 32)))
  59. {
  60. return index + 32;
  61. }
  62. #endif
  63. return 64;
  64. }
  65. template<>
  66. inline int64 WasmMath::Clz(int64 value)
  67. {
  68. DWORD index;
  69. #if TARGET_64
  70. if (_BitScanReverse64(&index, value))
  71. {
  72. return 63 - index;
  73. }
  74. #else
  75. if (_BitScanReverse(&index, (int32)(value >> 32)))
  76. {
  77. return 31 - index;
  78. }
  79. if (_BitScanReverse(&index, (int32)value))
  80. {
  81. return 63 - index;
  82. }
  83. #endif
  84. return 64;
  85. }
  86. template<>
  87. inline int WasmMath::PopCnt(int value)
  88. {
  89. return ::Math::PopCnt32(value);
  90. }
  91. template<>
  92. inline int64 WasmMath::PopCnt(int64 value)
  93. {
  94. uint64 v = (uint64)value;
  95. // https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel
  96. v = v - ((v >> 1) & 0x5555555555555555LL);
  97. v = (v & 0x3333333333333333LL) + ((v >> 2) & 0x3333333333333333LL);
  98. v = (v + (v >> 4)) & 0x0f0f0f0f0f0f0f0f;
  99. v = (uint64)(v * 0x0101010101010101LL) >> (sizeof(uint64) - 1) * CHAR_BIT;
  100. return (int64)v;
  101. }
  102. template<typename T>
  103. inline int WasmMath::Eqz(T value)
  104. {
  105. return value == 0;
  106. }
  107. template<>
  108. inline double WasmMath::Copysign(double aLeft, double aRight)
  109. {
  110. return _copysign(aLeft, aRight);
  111. }
  112. template<>
  113. inline float WasmMath::Copysign(float aLeft, float aRight)
  114. {
  115. uint32 res = ((*(uint32*)(&aLeft) & 0x7fffffffu) | (*(uint32*)(&aRight) & 0x80000000u));
  116. return *(float*)(&res);
  117. }
  118. template <typename T> bool WasmMath::LessThan(T aLeft, T aRight)
  119. {
  120. return aLeft < aRight;
  121. }
  122. template <typename T> bool WasmMath::LessOrEqual(T aLeft, T aRight)
  123. {
  124. return aLeft <= aRight;
  125. }
  126. template <typename STYPE,
  127. typename UTYPE,
  128. UTYPE MAX,
  129. UTYPE NEG_ZERO,
  130. UTYPE NEG_ONE,
  131. WasmMath::CmpPtr<UTYPE> CMP1,
  132. WasmMath::CmpPtr<UTYPE> CMP2>
  133. bool WasmMath::isInRange(STYPE srcVal)
  134. {
  135. Assert(sizeof(STYPE) == sizeof(UTYPE));
  136. UTYPE val = *reinterpret_cast<UTYPE*> (&srcVal);
  137. return (CMP1(val, MAX)) || (val >= NEG_ZERO && CMP2(val, NEG_ONE));
  138. }
  139. template <typename STYPE> bool WasmMath::isNaN(STYPE src)
  140. {
  141. return src != src;
  142. }
  143. template<typename T>
  144. inline T WasmMath::Trunc(T value)
  145. {
  146. if (value == 0.0)
  147. {
  148. return value;
  149. }
  150. else
  151. {
  152. T result;
  153. if (value < 0.0)
  154. {
  155. result = ceil(value);
  156. }
  157. else
  158. {
  159. result = floor(value);
  160. }
  161. // TODO: Propagating NaN sign for now awaiting consensus on semantics
  162. return result;
  163. }
  164. }
  165. template<typename T>
  166. inline T WasmMath::Nearest(T value)
  167. {
  168. if (value == 0.0)
  169. {
  170. return value;
  171. }
  172. else
  173. {
  174. T result;
  175. T u = ceil(value);
  176. T d = floor(value);
  177. T um = fabs(value - u);
  178. T dm = fabs(value - d);
  179. if (um < dm || (um == dm && floor(u / 2) == u / 2))
  180. {
  181. result = u;
  182. }
  183. else
  184. {
  185. result = d;
  186. }
  187. // TODO: Propagating NaN sign for now awaiting consensus on semantics
  188. return result;
  189. }
  190. }
  191. template<>
  192. inline int WasmMath::Rol(int aLeft, int aRight)
  193. {
  194. return _rotl(aLeft, aRight);
  195. }
  196. template<>
  197. inline int64 WasmMath::Rol(int64 aLeft, int64 aRight)
  198. {
  199. return _rotl64(aLeft, (int)aRight);
  200. }
  201. template<>
  202. inline int WasmMath::Ror(int aLeft, int aRight)
  203. {
  204. return _rotr(aLeft, aRight);
  205. }
  206. template<>
  207. inline int64 WasmMath::Ror(int64 aLeft, int64 aRight)
  208. {
  209. return _rotr64(aLeft, (int)aRight);
  210. }
  211. }