DVec3.inl 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. // SPDX-FileCopyrightText: 2021 Jorrit Rouwe
  2. // SPDX-License-Identifier: MIT
  3. #pragma once
  4. #ifdef JPH_USE_AVX2
  5. #include <Jolt/Core/HashCombine.h>
  6. // Create a std::hash for DVec3
  7. JPH_MAKE_HASHABLE(JPH::DVec3, t.GetX(), t.GetY(), t.GetZ())
  8. JPH_NAMESPACE_BEGIN
  9. DVec3::DVec3(Vec3Arg inRHS) :
  10. mValue(_mm256_cvtps_pd(inRHS.mValue))
  11. {
  12. }
  13. DVec3::DVec3(double inX, double inY, double inZ) :
  14. mValue(_mm256_set_pd(inZ, inZ, inY, inX)) // Assure Z and W are the same
  15. {
  16. }
  17. DVec3 DVec3::sZero()
  18. {
  19. return _mm256_setzero_pd();
  20. }
  21. DVec3 DVec3::sReplicate(double inV)
  22. {
  23. return _mm256_set1_pd(inV);
  24. }
  25. DVec3 DVec3::sLoadDouble3Unsafe(const double *inV)
  26. {
  27. __m256d v = _mm256_loadu_pd(inV);
  28. return sFixW(v);
  29. }
  30. Vec3 DVec3::ToVec3() const
  31. {
  32. return _mm256_cvtpd_ps(mValue);
  33. }
  34. DVec3 DVec3::sMin(DVec3Arg inV1, DVec3Arg inV2)
  35. {
  36. return _mm256_min_pd(inV1.mValue, inV2.mValue);
  37. }
  38. DVec3 DVec3::sMax(DVec3Arg inV1, DVec3Arg inV2)
  39. {
  40. return _mm256_max_pd(inV1.mValue, inV2.mValue);
  41. }
  42. DVec3 DVec3::sClamp(DVec3Arg inV, DVec3Arg inMin, DVec3Arg inMax)
  43. {
  44. return sMax(sMin(inV, inMax), inMin);
  45. }
  46. DVec3 DVec3::sEquals(DVec3Arg inV1, DVec3Arg inV2)
  47. {
  48. return _mm256_cmp_pd(inV1.mValue, inV2.mValue, _CMP_EQ_OQ);
  49. }
  50. DVec3 DVec3::sLess(DVec3Arg inV1, DVec3Arg inV2)
  51. {
  52. return _mm256_cmp_pd(inV1.mValue, inV2.mValue, _CMP_LT_OQ);
  53. }
  54. DVec3 DVec3::sLessOrEqual(DVec3Arg inV1, DVec3Arg inV2)
  55. {
  56. return _mm256_cmp_pd(inV1.mValue, inV2.mValue, _CMP_LE_OQ);
  57. }
  58. DVec3 DVec3::sGreater(DVec3Arg inV1, DVec3Arg inV2)
  59. {
  60. return _mm256_cmp_pd(inV1.mValue, inV2.mValue, _CMP_GT_OQ);
  61. }
  62. DVec3 DVec3::sGreaterOrEqual(DVec3Arg inV1, DVec3Arg inV2)
  63. {
  64. return _mm256_cmp_pd(inV1.mValue, inV2.mValue, _CMP_GE_OQ);
  65. }
  66. DVec3 DVec3::sFusedMultiplyAdd(DVec3Arg inMul1, DVec3Arg inMul2, DVec3Arg inAdd)
  67. {
  68. #ifdef JPH_USE_FMADD
  69. return _mm256_fmadd_pd(inMul1.mValue, inMul2.mValue, inAdd.mValue);
  70. #else
  71. return _mm256_add_pd(_mm256_mul_pd(inMul1.mValue, inMul2.mValue), inAdd.mValue);
  72. #endif
  73. }
  74. DVec3 DVec3::sSelect(DVec3Arg inV1, DVec3Arg inV2, DVec3Arg inControl)
  75. {
  76. return _mm256_blendv_pd(inV1.mValue, inV2.mValue, inControl.mValue);
  77. }
  78. DVec3 DVec3::sOr(DVec3Arg inV1, DVec3Arg inV2)
  79. {
  80. return _mm256_or_pd(inV1.mValue, inV2.mValue);
  81. }
  82. DVec3 DVec3::sXor(DVec3Arg inV1, DVec3Arg inV2)
  83. {
  84. return _mm256_xor_pd(inV1.mValue, inV2.mValue);
  85. }
  86. DVec3 DVec3::sAnd(DVec3Arg inV1, DVec3Arg inV2)
  87. {
  88. return _mm256_and_pd(inV1.mValue, inV2.mValue);
  89. }
  90. int DVec3::GetTrues() const
  91. {
  92. return _mm256_movemask_pd(mValue);
  93. }
  94. bool DVec3::TestAnyTrue() const
  95. {
  96. return (_mm256_movemask_pd(mValue) & 0x7) != 0;
  97. }
  98. bool DVec3::TestAllTrue() const
  99. {
  100. return (_mm256_movemask_pd(mValue) & 0x7) == 0x7;
  101. }
  102. bool DVec3::operator == (DVec3Arg inV2) const
  103. {
  104. return sEquals(*this, inV2).TestAllTrue();
  105. }
  106. bool DVec3::IsClose(DVec3Arg inV2, double inMaxDistSq) const
  107. {
  108. return (inV2 - *this).LengthSq() <= inMaxDistSq;
  109. }
  110. bool DVec3::IsNearZero(double inMaxDistSq) const
  111. {
  112. return LengthSq() <= inMaxDistSq;
  113. }
  114. DVec3 DVec3::operator * (DVec3Arg inV2) const
  115. {
  116. return _mm256_mul_pd(mValue, inV2.mValue);
  117. }
  118. DVec3 DVec3::operator * (double inV2) const
  119. {
  120. return _mm256_mul_pd(mValue, _mm256_set1_pd(inV2));
  121. }
  122. DVec3 operator * (double inV1, DVec3Arg inV2)
  123. {
  124. return _mm256_mul_pd(_mm256_set1_pd(inV1), inV2.mValue);
  125. }
  126. DVec3 DVec3::operator / (double inV2) const
  127. {
  128. return _mm256_div_pd(mValue, _mm256_set1_pd(inV2));
  129. }
  130. DVec3 &DVec3::operator *= (double inV2)
  131. {
  132. mValue = _mm256_mul_pd(mValue, _mm256_set1_pd(inV2));
  133. return *this;
  134. }
  135. DVec3 &DVec3::operator *= (DVec3Arg inV2)
  136. {
  137. mValue = _mm256_mul_pd(mValue, inV2.mValue);
  138. return *this;
  139. }
  140. DVec3 &DVec3::operator /= (double inV2)
  141. {
  142. mValue = _mm256_div_pd(mValue, _mm256_set1_pd(inV2));
  143. return *this;
  144. }
  145. DVec3 DVec3::operator + (DVec3Arg inV2) const
  146. {
  147. return _mm256_add_pd(mValue, inV2.mValue);
  148. }
  149. DVec3 &DVec3::operator += (DVec3Arg inV2)
  150. {
  151. mValue = _mm256_add_pd(mValue, inV2.mValue);
  152. return *this;
  153. }
  154. DVec3 DVec3::operator - () const
  155. {
  156. return _mm256_sub_pd(_mm256_setzero_pd(), mValue);
  157. }
  158. DVec3 DVec3::operator - (DVec3Arg inV2) const
  159. {
  160. return _mm256_sub_pd(mValue, inV2.mValue);
  161. }
  162. DVec3 &DVec3::operator -= (DVec3Arg inV2)
  163. {
  164. mValue = _mm256_sub_pd(mValue, inV2.mValue);
  165. return *this;
  166. }
  167. DVec3 DVec3::operator / (DVec3Arg inV2) const
  168. {
  169. inV2.CheckW();
  170. return _mm256_div_pd(mValue, inV2.mValue);
  171. }
  172. DVec3 DVec3::Abs() const
  173. {
  174. #if defined(JPH_USE_AVX512)
  175. return _mm256_range_pd(mValue, mValue, 0b1000);
  176. #else
  177. return _mm256_max_pd(_mm256_sub_pd(_mm256_setzero_pd(), mValue), mValue);
  178. #endif
  179. }
  180. DVec3 DVec3::Reciprocal() const
  181. {
  182. return sReplicate(1.0) / mValue;
  183. }
  184. DVec3 DVec3::Cross(DVec3Arg inV2) const
  185. {
  186. __m256d t1 = _mm256_permute4x64_pd(inV2.mValue, _MM_SHUFFLE(0, 0, 2, 1)); // Assure Z and W are the same
  187. t1 = _mm256_mul_pd(t1, mValue);
  188. __m256d t2 = _mm256_permute4x64_pd(mValue, _MM_SHUFFLE(0, 0, 2, 1)); // Assure Z and W are the same
  189. t2 = _mm256_mul_pd(t2, inV2.mValue);
  190. __m256d t3 = _mm256_sub_pd(t1, t2);
  191. return _mm256_permute4x64_pd(t3, _MM_SHUFFLE(0, 0, 2, 1)); // Assure Z and W are the same
  192. }
  193. double DVec3::Dot(DVec3Arg inV2) const
  194. {
  195. __m256d mul = _mm256_mul_pd(mValue, inV2.mValue);
  196. __m128d xy = _mm256_castpd256_pd128(mul);
  197. __m128d yx = _mm_shuffle_pd(xy, xy, 1);
  198. __m128d sum = _mm_add_pd(xy, yx);
  199. __m128d zw = _mm256_extractf128_pd(mul, 1);
  200. sum = _mm_add_pd(sum, zw);
  201. return _mm_cvtsd_f64(sum);
  202. }
  203. double DVec3::LengthSq() const
  204. {
  205. return Dot(*this);
  206. }
  207. DVec3 DVec3::Sqrt() const
  208. {
  209. return _mm256_sqrt_pd(mValue);
  210. }
  211. double DVec3::Length() const
  212. {
  213. return sqrt(Dot(*this));
  214. }
  215. DVec3 DVec3::Normalized() const
  216. {
  217. return *this / Length();
  218. }
  219. bool DVec3::IsNormalized(double inTolerance) const
  220. {
  221. return abs(LengthSq() - 1.0) <= inTolerance;
  222. }
  223. DVec3 DVec3::GetSign() const
  224. {
  225. __m256d minus_one = _mm256_set1_pd(-1.0);
  226. __m256d one = _mm256_set1_pd(1.0);
  227. return _mm256_or_pd(_mm256_and_pd(mValue, minus_one), one);
  228. }
  229. JPH_NAMESPACE_END
  230. #endif // JPH_USE_AVX2