DVec3.inl 5.6 KB

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