WasmMath.inl 4.9 KB

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