1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 #include "[float4.h]"19 #ifdef MATH_ENABLE_STL_SUPPORT20 #include "[myassert.h]"21 #include <utility>22 #include <iostream>23 #endif24 25 #include <stdlib.h>26 27 #include "[float2.h]"28 #include "[float3.h]"29 #include "../Geometry/AABB.h"30 #include "../Geometry/Sphere.h"31 #include "../Algorithm/Random/LCG.h"32 #include "[float4x4.h]"33 #include "[MathFunc.h]"34 #include "[SSEMath.h]"35 #include "[float4_sse.h]"36 #include "[float4_neon.h]"37 38 [MATH_BEGIN_NAMESPACE]39 40 using namespace std;41 42 [float4::float4](float x_, float y_, float z_, float w_)43 #if !defined(MATH_AUTOMATIC_SSE)44 45 :x(x_), y(y_), z(z_), w(w_)46 #endif47 {48 #if defined(MATH_AUTOMATIC_SSE)49 50 v = set_ps(w_, z_, y_, x_);51 #endif52 }53 54 [float4::float4](const [float3] &xyz, float w_)55 #if !defined(MATH_AUTOMATIC_SSE) || !defined(MATH_SSE)56 57 :x(xyz.[x]), y(xyz.[y]), z(xyz.[z]), w(w_)58 #endif59 {60 #if defined(MATH_AUTOMATIC_SSE) && defined(MATH_SSE)61 62 v = load_vec3(xyz.[ptr](), w_);63 #endif64 }65 66 [float4::float4](float x_, float y_, const [float2] &zw)67 #if !defined(MATH_AUTOMATIC_SSE)68 :x(x_), y(y_), z(zw.[x]), w(zw.[y])69 #endif70 {71 #if defined(MATH_AUTOMATIC_SSE)72 v = set_ps(zw.[y], zw.[x], y_, x_);73 #endif74 }75 76 [float4::float4](float x_, const [float2] &yz, float w_)77 #if !defined(MATH_AUTOMATIC_SSE)78 :x(x_), y(yz.[x]), z(yz.[y]), w(w_)79 #endif80 {81 #if defined(MATH_AUTOMATIC_SSE)82 v = set_ps(w_, yz.[y], yz.[x], x_);83 #endif84 }85 86 [float4::float4](float x_, const [float3] &yzw)87 #if !defined(MATH_AUTOMATIC_SSE)88 :x(x_), y(yzw.[x]), z(yzw.[y]), w(yzw.[z])89 #endif90 {91 #if defined(MATH_AUTOMATIC_SSE)92 v = set_ps(yzw.[z], yzw.[y], yzw.[x], x_);93 #endif94 }95 96 [float4::float4](const [float2] &xy, float z_, float w_)97 #if !defined(MATH_AUTOMATIC_SSE)98 :x(xy.[x]), y(xy.[y]), z(z_), w(w_)99 #endif100 {101 #if defined(MATH_AUTOMATIC_SSE)102 v = set_ps(w_, z_, xy.[y], xy.[x]);103 #endif104 }105 106 [float4::float4](const [float2] &xy, const [float2] &zw)107 #if !defined(MATH_AUTOMATIC_SSE)108 :x(xy.[x]), y(xy.[y]), z(zw.[x]), w(zw.[y])109 #endif110 {111 #if defined(MATH_AUTOMATIC_SSE)112 v = set_ps(zw.[y], zw.[x], xy.[y], xy.[x]);113 #endif114 }115 116 [float4::float4](const float *data)117 {118 [assume](data);119 #ifndef MATH_ENABLE_INSECURE_OPTIMIZATIONS120 if (!data)121 return;122 #endif123 #if defined(MATH_AUTOMATIC_SSE)124 v = loadu_ps(data);125 #else126 x = data[0];127 y = data[1];128 z = data[2];129 w = data[3];130 #endif131 }132 133 [CONST_WIN32] float [float4::At](int index) const134 {135 [assume](index >= 0);136 [assume](index < Size);137 #ifndef MATH_ENABLE_INSECURE_OPTIMIZATIONS138 if (index < 0 || index >= Size)139 return [FLOAT_NAN];140 #endif141 return ptr()[index];142 }143 144 float &[float4::At](int index)145 {146 [assume](index >= 0);147 [assume](index < Size);148 #ifndef MATH_ENABLE_INSECURE_OPTIMIZATIONS149 if (index < 0 || index >= Size)150 return ptr()[0];151 #endif152 return ptr()[index];153 }154 155 [float2] [float4::xy]() const156 {157 return [float2](x, y);158 }159 160 [float3] [float4::xyz]() const161 {162 return [float3](x, y, z);163 }164 165 [float2] [float4::Swizzled](int i, int j) const166 {167 return [float2](At(i), At(j));168 }169 170 [float3] [float4::Swizzled](int i, int j, int k) const171 {172 return [float3](At(i), At(j), At(k));173 }174 175 [float4] [float4::Swizzled](int i, int j, int k, int l) const176 {177 #if defined(MATH_AVX) && defined MATH_AUTOMATIC_SSE178 return vec4_permute(v, i, j, k, l);179 180 181 182 #else183 return [float4](At(i), At(j), At(k), At(l));184 #endif185 }186 187 [float4] [float4::xxxx]() const188 {189 #if defined(MATH_AUTOMATIC_SSE) && defined(MATH_SSE)190 return xxxx_ps(v);191 #else192 return [float4::FromScalar](x);193 #endif194 }195 196 [float4] [float4::yyyy]() const197 {198 #if defined(MATH_AUTOMATIC_SSE) && defined(MATH_SSE)199 return yyyy_ps(v);200 #else201 return [float4::FromScalar](x);202 #endif203 }204 205 [float4] [float4::zzzz]() const206 {207 #if defined(MATH_AUTOMATIC_SSE) && defined(MATH_SSE)208 return zzzz_ps(v);209 #else210 return [float4::FromScalar](x);211 #endif212 }213 214 [float4] [float4::xxxw]() const215 {216 #if defined(MATH_AUTOMATIC_SSE) && defined(MATH_SSE)217 return shuffle1_ps(v, _MM_SHUFFLE(3, 0, 0, 0));218 #else219 return [float4](x, x, x, w);220 #endif221 }222 223 [float4] [float4::yyyw]() const224 {225 #if defined(MATH_AUTOMATIC_SSE) && defined(MATH_SSE)226 return shuffle1_ps(v, _MM_SHUFFLE(3, 1, 1, 1));227 #else228 return [float4](y, y, y, w);229 #endif230 }231 232 [float4] [float4::zzzw]() const233 {234 #if defined(MATH_AUTOMATIC_SSE) && defined(MATH_SSE)235 return shuffle1_ps(v, _MM_SHUFFLE(3, 2, 2, 2));236 #else237 return [float4](z, z, z, w);238 #endif239 }240 241 [float4] [float4::wwww]() const242 {243 #if defined(MATH_AUTOMATIC_SSE) && defined(MATH_SSE)244 return wwww_ps(v);245 #else246 return [float4::FromScalar](x);247 #endif248 }249 250 #ifdef MATH_SIMD251 252 253 254 simd4f float4::LengthSq3_SSE() const255 {256 return dot3_ps3(v, v);257 }258 259 260 261 simd4f float4::Length3_SSE() const262 {263 return sqrt_ps(dot3_ps(v, v));264 }265 266 267 simd4f float4::LengthSq4_SSE() const268 {269 return dot4_ps(v, v);270 }271 272 273 simd4f float4::Length4_SSE() const274 {275 return sqrt_ps(dot4_ps(v, v));276 }277 278 void float4::Normalize3_Fast_SSE()279 {280 simd4f len = Length3_SSE();281 simd4f normalized = div_ps(v, len); 282 v = cmov_ps(v, normalized, sseMaskXYZ); 283 }284 285 simd4f float4::Normalize4_SSE()286 {287 simd4f len = Length4_SSE();288 simd4f isZero = cmplt_ps(len, simd4fEpsilon); 289 simd4f normalized = div_ps(v, len); 290 v = cmov_ps(normalized, [float4::unitX].v, isZero); 291 return len;292 }293 294 void float4::Normalize4_Fast_SSE()295 {296 simd4f recipLen = rsqrt_ps(dot4_ps(v, v));297 v = mul_ps(v, recipLen);298 }299 300 void float4::NormalizeW_SSE()301 {302 #ifdef MATH_SSE303 simd4f div = wwww_ps(v);304 v = div_ps(v, div);305 #elif defined(MATH_NEON)306 v = div_ps(v, vdupq_n_f32(vgetq_lane_f32(v, 3)));307 #endif308 }309 310 #endif311 312 float [float4::LengthSq3]() const313 {314 #ifdef MATH_AUTOMATIC_SSE315 return vec3_length_sq_float(v);316 #else317 return x*x + y*y + z*z;318 #endif319 }320 321 float [float4::Length3]() const322 {323 #ifdef MATH_AUTOMATIC_SSE324 return vec3_length_float(v);325 #else326 return [Sqrt](x*x + y*y + z*z);327 #endif328 }329 330 float [float4::LengthSq4]() const331 {332 #ifdef MATH_AUTOMATIC_SSE333 return vec4_length_sq_float(v);334 #else335 return x*x + y*y + z*z + w*w;336 #endif337 }338 339 float [float4::Length4]() const340 {341 #ifdef MATH_AUTOMATIC_SSE342 return vec4_length_float(v);343 #else344 return [Sqrt](x*x + y*y + z*z + w*w);345 #endif346 }347 348 float [float4::Normalize3]()349 {350 #if defined(MATH_AUTOMATIC_SSE) && defined(MATH_SSE)351 simd4f origLength;352 v = vec4_safe_normalize3(v, origLength);353 return s4f_x(origLength);354 #else355 [assume]([IsFinite]());356 float lengthSq = LengthSq3();357 if (lengthSq > 1[e]-6f)358 {359 float length = [Sqrt](lengthSq);360 float invLength = 1.f / length;361 x *= invLength;362 y *= invLength;363 z *= invLength;364 return length;365 }366 else367 {368 Set(1.f, 0.f, 0.f, w); 369 return 0; 370 }371 #endif372 }373 374 [float4] [float4::Normalized3]() const375 {376 #if defined(MATH_AUTOMATIC_SSE) && defined(MATH_SSE)377 simd4f origLength;378 return vec4_safe_normalize3(v, origLength);379 #else380 [float4] copy = *this;381 float length = copy.[Normalize3]();382 [assume](length > 0);383 MARK_UNUSED(length);384 return copy;385 #endif386 }387 388 float [float4::Normalize4]()389 {390 #if defined(MATH_AUTOMATIC_SSE) && defined(MATH_SSE)391 simd4f len = Normalize4_SSE();392 return s4f_x(len);393 #else394 [assume]([IsFinite]());395 float lengthSq = LengthSq4();396 if (lengthSq > 1[e]-6f)397 {398 float length = [Sqrt](lengthSq);399 *this *= 1.f / length;400 return length;401 }402 else403 {404 Set(1.f, 0.f, 0.f, 0.f); 405 return 0; 406 }407 #endif408 }409 410 [float4] [float4::Normalized4]() const411 {412 [float4] copy = *this;413 float length = copy.[Normalize4]();414 [assume](length > 0);415 MARK_UNUSED(length);416 return copy;417 }418 419 void [float4::NormalizeW]()420 {421 #if defined(MATH_AUTOMATIC_SSE) && defined(MATH_SSE)422 NormalizeW_SSE();423 #else424 if ([MATH_NS::Abs](w) > 1[e]-6f)425 {426 float invW = 1.f / w;427 x *= invW;428 y *= invW;429 z *= invW;430 w = 1.f;431 }432 #endif433 }434 435 bool [float4::IsWZeroOrOne](float [epsilon]) const436 {437 return [EqualAbs](w, 0.f, epsilon) || [EqualAbs](w, 1.f, epsilon);438 }439 440 bool [float4::IsZero4](float epsilonSq) const441 {442 return LengthSq4() <= epsilonSq;443 }444 445 bool [float4::IsZero3](float epsilonSq) const446 {447 return LengthSq3() <= epsilonSq;448 }449 450 bool [float4::IsNormalized4](float epsilonSq) const451 {452 return [MATH_NS::Abs](LengthSq4()-1.f) <= epsilonSq;453 }454 455 bool [float4::IsNormalized3](float epsilonSq) const456 {457 return [MATH_NS::Abs](LengthSq3()-1.f) <= epsilonSq;458 }459 460 void [float4::Scale3](float scalar)461 {462 #if defined(MATH_AUTOMATIC_SSE) && defined(MATH_SSE)463 simd4f scale = setx_ps(scalar);464 scale = _mm_shuffle_ps(scale, simd4fOne, _MM_SHUFFLE(0,0,0,0)); 465 scale = shuffle1_ps(scale, _MM_SHUFFLE(3,0,0,0)); 466 v = _mm_mul_ps(v, scale);467 #else468 x *= scalar;469 y *= scalar;470 z *= scalar;471 #endif472 }473 474 float [float4::ScaleToLength3](float newLength)475 {476 477 478 float length = LengthSq3();479 if (length < 1[e]-6f)480 return 0.f;481 482 length = [Sqrt](length);483 float scalar = newLength / length;484 x *= scalar;485 y *= scalar;486 z *= scalar;487 return length;488 }489 490 [float4] [float4::ScaledToLength3](float newLength) const491 {492 [assume](!IsZero3());493 494 [float4] v = *this;495 v.[ScaleToLength3](newLength);496 return v;497 }498 499 float [float4::ScaleToLength](float newLength)500 {501 float length = [Length]();502 float scalar = newLength / length;503 *this *= scalar;504 return length;505 }506 507 [float4] [float4::ScaledToLength](float newLength) const508 {509 [float4] v = *this;510 v.[ScaleToLength](newLength);511 return v;512 }513 514 bool [float4::IsFinite]() const515 {516 return [MATH_NS::IsFinite](x) && [MATH_NS::IsFinite](y) && [MATH_NS::IsFinite](z) && [MATH_NS::IsFinite](w);517 }518 519 bool [float4::IsPerpendicular3](const [float4] &other, float epsilonSq) const520 {521 float dot = [Dot3](other);522 return dot*dot <= epsilonSq * LengthSq() * other.[LengthSq]();523 }524 525 bool [float4::IsPerpendicular](const [float4] &other, float epsilonSq) const526 {527 float dot = [Dot](other);528 return dot*dot <= epsilonSq * LengthSq() * other.[LengthSq]();529 }530 531 bool [IsNeutralCLocale]();532 533 #ifdef MATH_ENABLE_STL_SUPPORT534 std::string [float4::ToString]() const535 {536 char str[256];537 sprintf(str, "(%.3f, %.3f, %.3f, %.3f)", x, y, z, w);538 return std::string(str);539 }540 541 std::string [float4::SerializeToString]() const542 {543 char str[256];544 char *s = [SerializeFloat](x, str); *s = ','; ++s;545 s = [SerializeFloat](y, s); *s = ','; ++s;546 s = [SerializeFloat](z, s); *s = ','; ++s;547 s = [SerializeFloat](w, s);548 [assert](s+1 - str < 256);549 MARK_UNUSED(s);550 return str;551 }552 553 std::string [float4::SerializeToCodeString]() const554 {555 return "float4(" + SerializeToString() + ")";556 }557 #endif558 559 [float4] [float4::FromString](const char *str, const char **outEndStr)560 {561 [assert]([IsNeutralCLocale]());562 [assume](str);563 if (!str)564 return [float4::nan];565 [MATH_SKIP_WORD](str, "float4");566 [MATH_SKIP_WORD](str, "(");567 [float4] f;568 f.[x] = [DeserializeFloat](str, &str);569 f.[y] = [DeserializeFloat](str, &str);570 f.[z] = [DeserializeFloat](str, &str);571 f.[w] = [DeserializeFloat](str, &str);572 if (*str == ')')573 ++str;574 if (*str == ',')575 ++str;576 if (outEndStr)577 *outEndStr = str;578 return f;579 }580 581 float [float4::SumOfElements]() const582 {583 #ifdef MATH_AUTOMATIC_SSE584 return sum_xyzw_float(v);585 #else586 return x + y + z + w;587 #endif588 }589 590 float [float4::ProductOfElements]() const591 {592 #ifdef MATH_AUTOMATIC_SSE593 return mul_xyzw_float(v);594 #else595 return x * y * z * w;596 #endif597 }598 599 float [float4::AverageOfElements]() const600 {601 return 0.25f * SumOfElements();602 }603 604 float [float4::MinElement]() const605 {606 return [MATH_NS::Min]([MATH_NS::Min](x, y), [MATH_NS::Min](z, w));607 }608 609 int [float4::MinElementIndex]() const610 {611 if (x < y)612 {613 if (z < w)614 return (x < z) ? 0 : 2;615 else616 return (x < w) ? 0 : 3;617 }618 else619 {620 if (z < w)621 return (y < z) ? 1 : 2;622 else623 return (y < w) ? 1 : 3;624 }625 }626 627 float [float4::MaxElement]() const628 {629 return [MATH_NS::Max]([MATH_NS::Max](x, y), [MATH_NS::Min](z, w));630 }631 632 int [float4::MaxElementIndex]() const633 {634 if (x > y)635 {636 if (z > w)637 return (x > z) ? 0 : 2;638 else639 return (x > w) ? 0 : 3;640 }641 else642 {643 if (z > w)644 return (y > z) ? 1 : 2;645 else646 return (y > w) ? 1 : 3;647 }648 }649 650 [float4] [float4::Abs]() const651 {652 #ifdef MATH_AUTOMATIC_SSE653 return abs_ps(v);654 #else655 return [float4]([MATH_NS::Abs](x), [MATH_NS::Abs](y), [MATH_NS::Abs](z), [MATH_NS::Abs](w));656 #endif657 }658 659 [float4] [float4::Neg3]() const660 {661 #ifdef MATH_AUTOMATIC_SSE662 return negate3_ps(v);663 #else664 return [float4](-x, -y, -z, w);665 #endif666 }667 668 [float4] [float4::Neg4]() const669 {670 #ifdef MATH_AUTOMATIC_SSE671 return negate_ps(v);672 #else673 return [float4](-x, -y, -z, -w);674 #endif675 }676 677 [float4] [float4::Recip3]() const678 {679 680 return [float4](1.f/x, 1.f/y, 1.f/z, w);681 }682 683 [float4] [float4::Recip4]() const684 {685 #ifdef MATH_AUTOMATIC_SSE686 return vec4_recip(v);687 #else688 return [float4](1.f/x, 1.f/y, 1.f/z, 1.f/w);689 #endif690 }691 692 [float4] [float4::RecipFast4]() const693 {694 #if defined(MATH_AUTOMATIC_SSE) && defined(MATH_SSE)695 return [float4](_mm_rcp_ps(v));696 #else697 return [float4](1.f/x, 1.f/y, 1.f/z, 1.f/w);698 #endif699 }700 701 [float4] [float4::Min](float ceil) const702 {703 #if defined(MATH_AUTOMATIC_SSE) && defined(MATH_SSE)704 return [float4](min_ps(v, set1_ps(ceil)));705 #else706 return [float4]([MATH_NS::Min](x, ceil), [MATH_NS::Min](y, ceil), [MATH_NS::Min](z, ceil), [MATH_NS::Min](w, ceil));707 #endif708 }709 710 [float4] [float4::Min](const [float4] &ceil) const711 {712 #ifdef MATH_AUTOMATIC_SSE713 return [float4](min_ps(v, ceil.v));714 #else715 return [float4]([MATH_NS::Min](x, ceil.[x]), [MATH_NS::Min](y, ceil.[y]), [MATH_NS::Min](z, ceil.[z]), [MATH_NS::Min](w, ceil.[w]));716 #endif717 }718 719 [float4] [float4::Max](float floor) const720 {721 #ifdef MATH_AUTOMATIC_SSE722 return [float4](max_ps(v, set1_ps(floor)));723 #else724 return [float4]([MATH_NS::Max](x, floor), [MATH_NS::Max](y, floor), [MATH_NS::Max](z, floor), [MATH_NS::Max](w, floor));725 #endif726 }727 728 [float4] [float4::Max](const [float4] &floor) const729 {730 #ifdef MATH_AUTOMATIC_SSE731 return [float4](max_ps(v, floor.v));732 #else733 return [float4]([MATH_NS::Max](x, floor.[x]), [MATH_NS::Max](y, floor.[y]), [MATH_NS::Max](z, floor.[z]), [MATH_NS::Max](w, floor.[w]));734 #endif735 }736 737 [float4] [float4::Clamp](const [float4] &floor, const [float4] &ceil) const738 {739 #ifdef MATH_AUTOMATIC_SSE740 return [float4](max_ps(min_ps(v, ceil.v), floor.v));741 #else742 return [float4]([MATH_NS::Clamp](x, floor.[x], ceil.[x]),743 [MATH_NS::Clamp](y, floor.[y], ceil.[y]),744 [MATH_NS::Clamp](z, floor.[z], ceil.[z]),745 [MATH_NS::Clamp](w, floor.[w], ceil.[w]));746 #endif747 }748 749 [float4] [float4::Clamp01]() const750 {751 #ifdef MATH_AUTOMATIC_SSE752 return [float4](max_ps(min_ps(v, simd4fOne), simd4fZero));753 #else754 return [float4]([MATH_NS::Clamp](x, 0.f, 1.f),755 [MATH_NS::Clamp](y, 0.f, 1.f),756 [MATH_NS::Clamp](z, 0.f, 1.f),757 [MATH_NS::Clamp](w, 0.f, 1.f));758 #endif759 }760 761 [float4] [float4::Clamp](float floor, float ceil) const762 {763 #ifdef MATH_AUTOMATIC_SSE764 return [float4](max_ps(min_ps(v, set1_ps(ceil)), set1_ps(floor)));765 #else766 return [float4]([MATH_NS::Clamp](x, floor, ceil),767 [MATH_NS::Clamp](y, floor, ceil),768 [MATH_NS::Clamp](z, floor, ceil),769 [MATH_NS::Clamp](w, floor, ceil));770 #endif771 }772 773 float [float4::Distance3Sq](const [float4] &rhs) const774 {775 #if defined(MATH_AUTOMATIC_SSE) && defined(MATH_SSE)776 return vec3_length_sq_float(sub_ps(v, rhs.v));777 #else778 float dx = x - rhs.[x];779 float dy = y - rhs.[y];780 float dz = z - rhs.[z];781 return dx*dx + dy*dy + dz*dz;782 #endif783 }784 785 float [float4::Distance3](const [float4] &rhs) const786 {787 #if defined(MATH_AUTOMATIC_SSE) && defined(MATH_SSE)788 return vec3_length_float(sub_ps(v, rhs.v));789 #else790 return [Sqrt](Distance3Sq(rhs));791 #endif792 }793 794 float [float4::Distance4Sq](const [float4] &rhs) const795 {796 #if defined(MATH_AUTOMATIC_SSE) && defined(MATH_SSE)797 return vec4_length_sq_float(sub_ps(v, rhs.v));798 #else799 float dx = x - rhs.[x];800 float dy = y - rhs.[y];801 float dz = z - rhs.[z];802 float dw = w - rhs.[w];803 return dx*dx + dy*dy + dz*dz + dw*dw;804 #endif805 }806 807 float [float4::Distance4](const [float4] &rhs) const808 {809 #if defined(MATH_AUTOMATIC_SSE) && defined(MATH_SSE)810 return vec4_length_float(sub_ps(v, rhs.v));811 #else812 return [Sqrt](Distance4Sq(rhs));813 #endif814 }815 816 float [float4::Dot3](const [float3] &rhs) const817 {818 #if defined(MATH_AUTOMATIC_SSE) && defined(MATH_SSE)819 return dot3_float(v, [float4](rhs, 0.f));820 #else821 return x * rhs.[x] + y * rhs.[y] + z * rhs.[z];822 #endif823 }824 825 float [float4::Dot3](const [float4] &rhs) const826 {827 #if defined(MATH_AUTOMATIC_SSE) && defined(MATH_SSE)828 return dot3_float(v, rhs.v);829 #else830 return x * rhs.[x] + y * rhs.[y] + z * rhs.[z];831 #endif832 }833 834 float [float4::Dot4](const [float4] &rhs) const835 {836 #if defined(MATH_AUTOMATIC_SSE) && defined(MATH_SSE)837 return dot4_float(v, rhs.v);838 #else839 return x * rhs.[x] + y * rhs.[y] + z * rhs.[z] + w * rhs.[w];840 #endif841 }842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 [float4] [float4::Cross3](const [float3] &rhs) const865 {866 #if defined(MATH_AUTOMATIC_SSE) && defined(MATH_SSE)867 return [float4](cross_ps(v, load_vec3(rhs.[ptr](), 0.f)));868 #else869 [float4] dst;870 dst.[x] = y * rhs.[z] - z * rhs.[y];871 dst.y = z * rhs.[x] - x * rhs.[z];872 dst.z = x * rhs.[y] - y * rhs.[x];873 dst.w = 0.f;874 return dst;875 #endif876 }877 878 [float4] [float4::Cross3](const [float4] &rhs) const879 {880 #if defined(MATH_AUTOMATIC_SSE) && defined(MATH_SSE)881 [assert]((((uintptr_t)&rhs) & 15) == 0); 882 [assert]((((uintptr_t)this) & 15) == 0);883 return [float4](cross_ps(v, rhs.v));884 #else885 return [Cross3](rhs.[xyz]());886 #endif887 }888 889 [float4x4] [float4::OuterProduct](const [float4] &rhs) const890 {891 const [float4] &u = *this;892 const [float4] &v = rhs;893 return [float4x4](u[0]*v[0], u[0]*v[1], u[0]*v[2], u[0]*v[3],894 u[1]*v[0], u[1]*v[1], u[1]*v[2], u[1]*v[3],895 u[2]*v[0], u[2]*v[1], u[2]*v[2], u[2]*v[3],896 u[3]*v[0], u[3]*v[1], u[3]*v[2], u[3]*v[3]);897 }898 899 [float4] [float4::Perpendicular3](const [float3] &hint, const [float3] &hint2) const900 {901 [assume](!this->IsZero3());902 [assume]([EqualAbs](w, 0));903 [assume](hint.[IsNormalized]());904 [assume](hint2.[IsNormalized]());905 [float3] v = this->[Cross3](hint).[xyz]();906 float len = v.[Normalize]();907 if (len == 0)908 return [float4](hint2, 0);909 else910 return [float4](v, 0);911 }912 913 [float4] [float4::Perpendicular](const [float4] &hint, const [float4] &hint2) const914 {915 [assume](!this->IsZero3());916 [assume]([EqualAbs](w, 0));917 [assume](hint.[IsNormalized]());918 [assume](hint2.[IsNormalized]());919 [float4] v = this->[Cross](hint);920 float len = v.Normalize();921 if (len == 0)922 return hint2;923 else924 return v;925 }926 927 [float4] [float4::AnotherPerpendicular3](const [float3] &hint, const [float3] &hint2) const928 {929 [float4] firstPerpendicular = Perpendicular3(hint, hint2);930 [float4] v = this->[Cross3](firstPerpendicular);931 return v.[Normalized3]();932 }933 934 [float4] [float4::AnotherPerpendicular](const [float4] &hint, const [float4] &hint2) const935 {936 [float4] firstPerpendicular = Perpendicular(hint, hint2);937 [float4] v = this->[Cross](firstPerpendicular);938 return v.[Normalized]();939 }940 941 void [float4::PerpendicularBasis]([float4] &outB, [float4] &outC) const942 {943 #if defined(MATH_AUTOMATIC_SSE) && defined(MATH_SSE)944 945 946 basis_ps(this->v, &outB.v, &outC.v);947 #else948 949 950 [float4] a = this->[Abs]();951 952 [float4] q;953 if (a.[x] <= a.[y])954 {955 if (a.[x] <= a.[z]) q = [float4](1,0,0,0);956 else q = [float4](0,0,1,0);957 }958 else if (a.[y] <= a.[z]) q = [float4](0,1,0,0);959 else q = [float4](0,0,1,0);960 961 outB = this->[Cross](q).[Normalized]();962 outC = this->[Cross](outB).[Normalized]();963 #endif964 }965 966 [float4] [float4::RandomPerpendicular]([LCG] &rng) const967 {968 return Perpendicular(RandomDir(rng));969 }970 971 [float4] [float4::Reflect3](const [float3] &normal) const972 {973 [assume2](normal.[IsNormalized](), normal.[SerializeToCodeString](), normal.[Length]());974 [assume]([EqualAbs](w, 0));975 return 2.f * this->ProjectToNorm3(normal) - *this;976 }977 978 [float4] [float4::Reflect](const [float4] &normal) const979 {980 [assume2](normal.[IsNormalized](), normal.[SerializeToCodeString](), normal.[Length]());981 [assume]([EqualAbs](w, 0));982 return 2.f * this->ProjectToNorm(normal) - *this;983 }984 985 986 [float4] [float4::Refract](const [float4] &normal, float negativeSideRefractionIndex, float positiveSideRefractionIndex) const987 {988 989 float n = negativeSideRefractionIndex / positiveSideRefractionIndex;990 float cosI = this->[Dot](normal);991 float sinT2 = n*n*(1.f - cosI*cosI);992 if (sinT2 > 1.f) 993 return (-*this).Reflect(normal);994 return n * *this - (n + [Sqrt](1.f - sinT2)) * normal;995 }996 997 float [float4::AngleBetween3](const [float4] &other) const998 {999 float cosa = [Dot3](other) / [Sqrt](LengthSq3() * other.[LengthSq3]());1000 if (cosa >= 1.f)1001 return 0.f;1002 else if (cosa <= -1.f)1003 return [pi];1004 else1005 return acos(cosa);1006 }1007 1008 float [float4::AngleBetweenNorm3](const [float4] &other) const1009 {1010 [assume](this->IsNormalized3());1011 [assume](other.[IsNormalized3]());1012 return acos([Dot3](other));1013 }1014 1015 float [float4::AngleBetween4](const [float4] &other) const1016 {1017 float cosa = [Dot4](other) / [Sqrt](LengthSq4() * other.[LengthSq4]());1018 if (cosa >= 1.f)1019 return 0.f;1020 else if (cosa <= -1.f)1021 return [pi];1022 else1023 return acos(cosa);1024 }1025 1026 float [float4::AngleBetweenNorm4](const [float4] &other) const1027 {1028 [assume](this->IsNormalized4());1029 [assume](other.[IsNormalized4]());1030 return acos([Dot4](other));1031 }1032 1033 [float4] [float4::ProjectTo3](const [float3] &target) const1034 {1035 [assume](!target.[IsZero]());1036 [assume](this->IsWZeroOrOne());1037 return [float4](target * [MATH_NS::Dot](xyz(), target) / target.[LengthSq](), w);1038 }1039 1040 [float4] [float4::ProjectTo](const [float4] &target) const1041 {1042 [assume](!target.[IsZero]());1043 [assume](this->IsWZeroOrOne());1044 return target * (this->[Dot](target) / target.[LengthSq]());1045 }1046 1047 [float4] [float4::ProjectToNorm3](const [float3] &target) const1048 {1049 [assume](target.[IsNormalized]());1050 [assume](this->IsWZeroOrOne());1051 return [float4](target * [MATH_NS::Dot](xyz(), target), w);1052 }1053 1054 [float4] [float4::ProjectToNorm](const [float4] &target) const1055 {1056 [assume](target.[IsNormalized]());1057 [assume](this->IsWZeroOrOne());1058 return target * this->[Dot](target);1059 }1060 1061 bool [MUST_USE_RESULT] [float4::AreCollinear](const [float4] &p1, const [float4] &p2, const [float4] &p3, float [epsilon])1062 {1063 return (p2 - p1).Cross(p3 - p1).LengthSq() <= [epsilon];1064 }1065 1066 [float4] [float4::Lerp](const [float4] &b, float t) const1067 {1068 [assume]([EqualAbs](this->w, b.[w]));1069 [assume](0.f <= t && t <= 1.f);1070 #if defined(MATH_AUTOMATIC_SSE) && defined(MATH_SSE)1071 return vec4_lerp(v, b.v, t);1072 #else1073 return (1.f - t) * *this + t * b;1074 #endif1075 }1076 1077 [float4] [float4::Lerp](const [float4] &a, const [float4] &b, float t)1078 {1079 return a.[Lerp](b, t);1080 }1081 1082 bool [MUST_USE_RESULT] [float4::AreOrthogonal](const [float4] &a, const [float4] &b, float epsilon)1083 {1084 return a.[IsPerpendicular](b, epsilon);1085 }1086 1087 bool [MUST_USE_RESULT] [float4::AreOrthogonal](const [float4] &a, const [float4] &b, const [float4] &c, float epsilon)1088 {1089 return a.[IsPerpendicular](b, epsilon) &&1090 a.[IsPerpendicular](c, epsilon) &&1091 b.[IsPerpendicular](c, epsilon);1092 }1093 1094 void [float4::Orthonormalize]([float4] &a, [float4] &b)1095 {1096 [assume](!a.[IsZero]());1097 [assume](!b.[IsZero]());1098 a.[Normalize]();1099 b -= b.[ProjectToNorm](a);1100 b.[Normalize]();1101 }1102 1103 void [float4::Orthonormalize]([float4] &a, [float4] &b, [float4] &c)1104 {1105 [assume](!a.[IsZero]());1106 a.[Normalize]();1107 b -= b.[ProjectToNorm](a);1108 [assume](!b.[IsZero]());1109 b.[Normalize]();1110 c -= c.[ProjectToNorm](a);1111 c -= c.[ProjectToNorm](b);1112 [assume](!c.[IsZero]());1113 c.[Normalize]();1114 }1115 1116 bool [MUST_USE_RESULT] [float4::AreOrthonormal](const [float4] &a, const [float4] &b, float epsilon)1117 {1118 return a.[IsPerpendicular](b, epsilon) && a.[IsNormalized](epsilon*epsilon) && b.[IsNormalized](epsilon*epsilon);1119 }1120 1121 bool [MUST_USE_RESULT] [float4::AreOrthonormal](const [float4] &a, const [float4] &b, const [float4] &c, float epsilon)1122 {1123 return a.[IsPerpendicular](b, epsilon) &&1124 a.[IsPerpendicular](c, epsilon) &&1125 b.[IsPerpendicular](c, epsilon) &&1126 a.[IsNormalized](epsilon*epsilon) &&1127 b.[IsNormalized](epsilon*epsilon) &&1128 c.[IsNormalized](epsilon*epsilon);1129 }1130 1131 [float4] [float4::FromScalar](float scalar)1132 {1133 #ifdef MATH_AUTOMATIC_SSE1134 return set1_ps(scalar);1135 #else1136 return [float4](scalar, scalar, scalar, scalar);1137 #endif1138 }1139 1140 [float4] [float4::FromScalar](float scalar, float w_)1141 {1142 #if defined(MATH_AUTOMATIC_SSE) && defined(MATH_SSE)1143 simd4f s = set1_ps(scalar);1144 simd4f highPart = _mm_unpacklo_ps(s, _mm_set_ss(w_)); 1145 return _mm_movelh_ps(s, highPart); 1146 #else1147 return [float4](scalar, scalar, scalar, w_);1148 #endif1149 }1150 1151 void [float4::SetFromScalar](float scalar)1152 {1153 #ifdef MATH_AUTOMATIC_SSE1154 v = set1_ps(scalar);1155 #else1156 x = scalar;1157 y = scalar;1158 z = scalar;1159 w = scalar;1160 #endif1161 }1162 1163 void [float4::Set](float x_, float y_, float z_, float w_)1164 {1165 #ifdef MATH_AUTOMATIC_SSE1166 v = set_ps(w_, z_, y_, x_);1167 #else1168 x = x_;1169 y = y_;1170 z = z_;1171 w = w_;1172 #endif1173 }1174 1175 void [float4::SetFromScalar](float scalar, float w_)1176 {1177 #ifdef MATH_AUTOMATIC_SSE1178 #ifdef MATH_SSE1179 simd4f s = set1_ps(scalar);1180 simd4f highPart = _mm_unpacklo_ps(s, _mm_set_ss(w_)); 1181 v = _mm_movelh_ps(s, highPart); 1182 #else1183 v = set_ps(w_, scalar, scalar, scalar);1184 #endif1185 #else1186 x = scalar;1187 y = scalar;1188 z = scalar;1189 w = w_;1190 #endif1191 }1192 1193 void [float4::SetFromSphericalCoordinates](float azimuth, float inclination, float radius)1194 {1195 float cx = [Cos](inclination);1196 float sin, cos;1197 [SinCos](azimuth, sin, cos);1198 x = cx * sin * radius;1199 y = -[Sin](inclination) * radius;1200 z = cx * cos * radius;1201 w = 0.f;1202 }1203 1204 [float4] [MUST_USE_RESULT] [float4::FromSphericalCoordinates](float azimuth, float inclination, float radius)1205 {1206 [float4] v;1207 v.[SetFromSphericalCoordinates](azimuth, inclination, radius);1208 return v;1209 }1210 1211 void [float4::SetFromSphericalCoordinates](float azimuth, float inclination)1212 {1213 [float4] v, s, c;1214 v.[x] = inclination;1215 v.[y] = azimuth;1216 [SinCos2](v, s, c);1217 x = c.[x] * s.[y];1218 y = -s.[x];1219 z = c.[x] * c.[y];1220 w = 0.f;1221 }1222 1223 [float4] [MUST_USE_RESULT] [float4::FromSphericalCoordinates](float azimuth, float inclination)1224 {1225 [float4] v;1226 v.[SetFromSphericalCoordinates](azimuth, inclination);1227 return v;1228 }1229 1230 [float3] [float4::ToSphericalCoordinates]() const1231 {1232 1233 [float4] v = *this;1234 float len = v.[Normalize]();1235 if (len <= 1[e]-5f)1236 return [float3::zero];1237 float azimuth = atan2(v.[x], v.[z]);1238 float inclination = asin(-v.[y]);1239 return [float3](azimuth, inclination, len);1240 }1241 1242 [float2] [float4::ToSphericalCoordinatesNormalized]() const1243 {1244 [assume](IsNormalized());1245 float azimuth = atan2(x, z);1246 float inclination = asin(-y);1247 return [float2](azimuth, inclination);1248 }1249 1250 bool [float4::Equals](const [float4] &other, float epsilon) const1251 {1252 return [MATH_NS::Abs](x - other.[x]) < epsilon &&1253 [MATH_NS::Abs](y - other.[y]) < epsilon &&1254 [MATH_NS::Abs](z - other.[z]) < epsilon &&1255 [MATH_NS::Abs](w - other.[w]) < [epsilon];1256 }1257 1258 bool [float4::Equals](float x_, float y_, float z_, float w_, float epsilon) const1259 {1260 return [MATH_NS::Abs](x - x_) < epsilon &&1261 [MATH_NS::Abs](y - y_) < epsilon &&1262 [MATH_NS::Abs](z - z_) < epsilon &&1263 [MATH_NS::Abs](w - w_) < [epsilon];1264 }1265 1266 bool [float4::BitEquals](const [float4] &other) const1267 {1268 return [ReinterpretAsU32](x) == [ReinterpretAsU32](other.[x]) &&1269 [ReinterpretAsU32](y) == [ReinterpretAsU32](other.[y]) &&1270 [ReinterpretAsU32](z) == [ReinterpretAsU32](other.[z]) &&1271 [ReinterpretAsU32](w) == [ReinterpretAsU32](other.[w]);1272 }1273 1274 [float4] [MUST_USE_RESULT] [float4::RandomDir]([LCG] &lcg, float length)1275 {1276 return [DIR_TO_FLOAT4]([Sphere]([POINT_VEC_SCALAR](0.f), length).RandomPointOnSurface(lcg) - vec([POINT_VEC_SCALAR](0.f)));1277 }1278 1279 [float4] [MUST_USE_RESULT] [float4::RandomSphere]([LCG] &lcg, const [float4] ¢er, float radius)1280 {1281 return [POINT_TO_FLOAT4]([Sphere]([FLOAT4_TO_POINT](center), radius).RandomPointInside(lcg));1282 }1283 1284 [float4] [MUST_USE_RESULT] [float4::RandomBox]([LCG] &lcg, float xmin, float xmax, float ymin, float ymax, float zmin, float zmax)1285 {1286 return RandomBox(lcg, [float4](xmin, ymin, zmin, 1.f), [float4](xmax, ymax, zmax, 1.f));1287 }1288 1289 [float4] [MUST_USE_RESULT] [float4::RandomBox]([LCG] &lcg, float minElem, float maxElem)1290 {1291 return RandomBox(lcg, [float4](minElem, minElem, minElem, 1.f), [float4](maxElem, maxElem, maxElem, 1.f));1292 }1293 1294 [float4] [MUST_USE_RESULT] [float4::RandomBox]([LCG] &lcg, const [float4] &minValues, const [float4] &maxValues)1295 {1296 return [POINT_TO_FLOAT4]([AABB]([FLOAT4_TO_POINT](minValues), [FLOAT4_TO_POINT](maxValues)).RandomPointInside(lcg));1297 }1298 1299 [float4] [float4::RandomGeneral]([LCG] &lcg, float minElem, float maxElem)1300 {1301 return [float4](lcg.[Float](minElem, maxElem), lcg.[Float](minElem, maxElem), lcg.[Float](minElem, maxElem), lcg.[Float](minElem, maxElem));1302 }1303 1304 [float4] [float4::operator +](const [float4] &rhs) const1305 {1306 #ifdef MATH_AUTOMATIC_SSE1307 return add_ps(v, rhs.v);1308 #else1309 return [float4](x + rhs.[x], y + rhs.[y], z + rhs.[z], w + rhs.[w]);1310 #endif1311 }1312 1313 [float4] [float4::operator -](const [float4] &rhs) const1314 {1315 #ifdef MATH_AUTOMATIC_SSE1316 return sub_ps(v, rhs.v);1317 #else1318 return [float4](x - rhs.[x], y - rhs.[y], z - rhs.[z], w - rhs.[w]);1319 #endif1320 }1321 1322 [float4] [float4::operator -]() const1323 {1324 #ifdef MATH_AUTOMATIC_SSE1325 return negate_ps(v);1326 #else1327 return [float4](-x, -y, -z, -w);1328 #endif1329 }1330 1331 [float4] [float4::operator *](float scalar) const1332 {1333 #ifdef MATH_AUTOMATIC_SSE1334 return vec4_mul_float(v, scalar);1335 #else1336 return [float4](x * scalar, y * scalar, z * scalar, w * scalar);1337 #endif1338 }1339 1340 [float4] [operator *](float scalar, const [float4] &rhs)1341 {1342 #ifdef MATH_AUTOMATIC_SSE1343 return vec4_mul_float(rhs.v, scalar);1344 #else1345 return [float4](scalar * rhs.[x], scalar * rhs.[y], scalar * rhs.[z], scalar * rhs.[w]);1346 #endif1347 }1348 1349 [float4] [float4::operator /](float scalar) const1350 {1351 #ifdef MATH_AUTOMATIC_SSE1352 return vec4_div_float(v, scalar);1353 #else1354 float invScalar = 1.f / scalar;1355 return [float4](x * invScalar, y * invScalar, z * invScalar, w * invScalar);1356 #endif1357 }1358 1359 [float4] &[float4::operator +=](const [float4] &rhs)1360 {1361 #ifdef MATH_AUTOMATIC_SSE1362 v = add_ps(v, rhs.v);1363 #else1364 x += rhs.[x];1365 y += rhs.[y];1366 z += rhs.[z];1367 w += rhs.[w];1368 #endif1369 1370 return *this;1371 }1372 1373 [float4] &[float4::operator -=](const [float4] &rhs)1374 {1375 #ifdef MATH_AUTOMATIC_SSE1376 v = sub_ps(v, rhs.v);1377 #else1378 x -= rhs.[x];1379 y -= rhs.[y];1380 z -= rhs.[z];1381 w -= rhs.[w];1382 #endif1383 1384 return *this;1385 }1386 1387 [float4] &[float4::operator *=](float scalar)1388 {1389 #ifdef MATH_AUTOMATIC_SSE1390 v = vec4_mul_float(v, scalar);1391 #else1392 x *= scalar;1393 y *= scalar;1394 z *= scalar;1395 w *= scalar;1396 #endif1397 1398 return *this;1399 }1400 1401 [float4] &[float4::operator /=](float scalar)1402 {1403 #ifdef MATH_AUTOMATIC_SSE1404 v = vec4_div_float(v, scalar);1405 #else1406 float invScalar = 1.f / scalar;1407 x *= invScalar;1408 y *= invScalar;1409 z *= invScalar;1410 w *= invScalar;1411 #endif1412 1413 return *this;1414 }1415 1416 [float4] [float4::Add](float s) const1417 {1418 #ifdef MATH_AUTOMATIC_SSE1419 return vec4_add_float(v, s);1420 #else1421 return [float4](x + s, y + s, z + s, w + s);1422 #endif1423 }1424 1425 [float4] [float4::Sub](float s) const1426 {1427 #ifdef MATH_AUTOMATIC_SSE1428 return vec4_sub_float(v, s);1429 #else1430 return [float4](x - s, y - s, z - s, w - s);1431 #endif1432 }1433 1434 [float4] [float4::SubLeft](float s) const1435 {1436 #ifdef MATH_AUTOMATIC_SSE1437 return float_sub_vec4(s, v);1438 #else1439 return [float4](s - x, s - y, s - z, s - w);1440 #endif1441 }1442 1443 [float4] [float4::DivLeft](float s) const1444 {1445 #ifdef MATH_AUTOMATIC_SSE1446 return float_div_vec4(s, v);1447 #else1448 return [float4](s / x, s / y, s / z, s / w);1449 #endif1450 }1451 1452 [float4] [float4::Mul](const [float4] &rhs) const1453 {1454 #ifdef MATH_AUTOMATIC_SSE1455 return mul_ps(v, rhs.v);1456 #else1457 return [float4](x * rhs.[x], y * rhs.[y], z * rhs.[z], w * rhs.[w]);1458 #endif1459 }1460 1461 [float4] [float4::Div](const [float4] &rhs) const1462 {1463 #ifdef MATH_AUTOMATIC_SSE1464 return div_ps(v, rhs.v);1465 #else1466 return [float4](x / rhs.[x], y / rhs.[y], z / rhs.[z], w / rhs.[w]);1467 #endif1468 }1469 1470 #ifdef MATH_ENABLE_STL_SUPPORT1471 std::ostream &[operator <<](std::ostream &out, const [float4] &rhs)1472 {1473 std::string str = rhs.[ToString]();1474 out << str;1475 return out;1476 }1477 #endif1478 1479 const [float4] [float4::zero] = [float4](0, 0, 0, 0);1480 const [float4] [float4::one] = [float4](1, 1, 1, 1);1481 const [float4] [float4::unitX] = [float4](1, 0, 0, 0);1482 const [float4] [float4::unitY] = [float4](0, 1, 0, 0);1483 const [float4] [float4::unitZ] = [float4](0, 0, 1, 0);1484 const [float4] [float4::unitW] = [float4](0, 0, 0, 1);1485 const [float4] [float4::nan] = [float4]([FLOAT_NAN], [FLOAT_NAN], [FLOAT_NAN], [FLOAT_NAN]);1486 const [float4] [float4::inf] = [float4]([FLOAT_INF], [FLOAT_INF], [FLOAT_INF], [FLOAT_INF]);1487 1488 [MATH_END_NAMESPACE] Go back to previous page