• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef API_BASE_MATH_VECTOR_H
17 #define API_BASE_MATH_VECTOR_H
18 
19 #include <cstddef>
20 #include <cstdint>
21 #if defined(BASE_SIMD) && defined(_M_X64)
22 #include <immintrin.h>
23 #elif defined(_M_ARM64) || defined(__ARM_ARCH_ISA_A64)
24 #include <arm_neon.h>
25 #endif
26 #include <base/math/mathf.h>
27 #include <base/namespace.h>
28 
BASE_BEGIN_NAMESPACE()29 BASE_BEGIN_NAMESPACE()
30 namespace Math {
31 #include <base/math/disable_warning_4201_heading.h>
32 
33 class Vec2;
34 class Vec3;
35 class Vec4;
36 
37 /** @ingroup group_math_vector */
38 /** Vector2 presentation */
39 class Vec2 final {
40 public:
41     union {
42         struct {
43             float x;
44             float y;
45         };
46         float data[2];
47     };
48     /** Subscript operator */
49     constexpr float& operator[](size_t index)
50     {
51         return data[index];
52     }
53 
54     /** Subscript operator */
55     constexpr const float& operator[](size_t index) const
56     {
57         return data[index];
58     }
59 
60     // Constructors
61     /** Default constructor */
62     inline constexpr Vec2() noexcept : data {} {}
63     /** Constructor for using floats as input */
64     inline constexpr Vec2(float xParameter, float yParameter) noexcept : x(xParameter), y(yParameter) {}
65     /** Constructor for using array of floats as input */
66     inline constexpr Vec2(const float parameter[2]) noexcept : x(parameter[0]), y(parameter[1]) {}
67     ~Vec2() = default;
68 
69     /** Add operator */
70     inline constexpr Vec2 operator+(const Vec2& v2) const
71     {
72         return Vec2(x + v2.x, y + v2.y);
73     }
74     /** Add operator */
75     inline constexpr Vec2& operator+=(const Vec2& rhs)
76     {
77         x += rhs.x;
78         y += rhs.y;
79         return *this;
80     }
81 
82     /** Negate operator */
83     inline constexpr Vec2 operator-() const
84     {
85         return Vec2(-x, -y);
86     }
87 
88     /** Subtract operator */
89     inline constexpr Vec2 operator-(const Vec2& v2) const
90     {
91         return Vec2(x - v2.x, y - v2.y);
92     }
93     /** Subtract operator */
94     inline constexpr Vec2& operator-=(const Vec2& rhs)
95     {
96         x -= rhs.x;
97         y -= rhs.y;
98         return *this;
99     }
100 
101     /** Multiply operator */
102     inline constexpr Vec2 operator*(const Vec2& v2) const
103     {
104         return Vec2(x * v2.x, y * v2.y);
105     }
106     /** Multiply operator */
107     inline constexpr Vec2& operator*=(const Vec2& rhs)
108     {
109         x *= rhs.x;
110         y *= rhs.y;
111         return *this;
112     }
113 
114     /** Divide operator */
115     inline constexpr Vec2 operator/(const Vec2& v2) const
116     {
117         return Vec2(x / v2.x, y / v2.y);
118     }
119     /** Divide operator */
120     inline constexpr Vec2& operator/=(const Vec2& rhs)
121     {
122         x /= rhs.x;
123         y /= rhs.y;
124         return *this;
125     }
126 
127     /** Multiplies vector by float value */
128     inline constexpr Vec2 operator*(float d) const
129     {
130         return Vec2(x * d, y * d);
131     }
132     /** Multiplies vector by float value */
133     inline constexpr Vec2& operator*=(float d)
134     {
135         x *= d;
136         y *= d;
137         return *this;
138     }
139 
140     /** Divides vector by float value */
141     inline constexpr Vec2 operator/(float d) const
142     {
143         return Vec2(x / d, y / d);
144     }
145     /** Divides vector by float value */
146     inline constexpr Vec2& operator/=(float d)
147     {
148         x /= d;
149         y /= d;
150         return *this;
151     }
152 
153     /** Add float from vector */
154     inline constexpr Vec2 operator+(float d) const
155     {
156         return Vec2(x + d, y + d);
157     }
158 
159     /** Subtract float from vector */
160     inline constexpr Vec2 operator-(float d) const
161     {
162         return Vec2(x - d, y - d);
163     }
164     /** Subtract float from vector */
165     inline constexpr Vec2& operator-=(float d)
166     {
167         x -= d;
168         y -= d;
169         return *this;
170     }
171 
172     // Equality operators
173     /** Equality operator, returns true if the vectors are equal */
174     constexpr bool operator==(const Vec2& rhs) const
175     {
176         const Vec2 temp = *this - rhs;
177         const float sqmgt = temp.x * temp.x + temp.y * temp.y;
178 
179         // Returns false in the presence of NaN values
180         return sqmgt < Math::EPSILON * Math::EPSILON;
181     }
182 
183     /** Inequality operator, returns true if vectors are different */
184     constexpr bool operator!=(const Vec2& rhs) const
185     {
186         // Returns true in the presence of NaN values
187         return !(*this == rhs);
188     }
189 };
190 
191 // Assert that Vec2 is the same as 2 floats
192 static_assert(sizeof(Vec2) == 2 * sizeof(float));
193 
194 static constexpr Vec2 ZERO_VEC2(0.0f, 0.0f);
195 
196 /** @ingroup group_math_vector */
197 /** Vector3 presentation */
198 class Vec3 final {
199 public:
200     union {
201         struct {
202             float x;
203             float y;
204             float z;
205         };
206         float data[3];
207     };
208     /** Subscript operator */
209     constexpr float& operator[](size_t index);
210     /** Subscript operator */
211     constexpr const float& operator[](size_t index) const;
212 
213     // Constructors
214     /** Default constructor */
215     inline constexpr Vec3() noexcept;
216     /** Constructor for using floats as input */
217     inline constexpr Vec3(float xParameter, float yParameter, float zParameter) noexcept;
218     /** Constructor for using array of floats as input */
219     inline constexpr Vec3(const float d[]) noexcept;
220     /** Constructor for using vector4 as input, discards w component */
221     inline constexpr Vec3(const Vec4& vec) noexcept;
222     ~Vec3() = default;
223 
224     // Vec3 to Vec3 operations
225     /** Add operator */
226     inline constexpr Vec3 operator+(const Vec3& v2) const;
227     /** Add operator */
228     inline constexpr Vec3& operator+=(const Vec3& rhs);
229 
230     /** Negate operator */
231     inline constexpr Vec3 operator-() const;
232 
233     /** Subtract operator */
234     inline constexpr Vec3 operator-(const Vec3& v2) const;
235     /** Subtract operator */
236     inline constexpr Vec3& operator-=(const Vec3& rhs);
237 
238     /** Multiply operator */
239     inline constexpr Vec3 operator*(const Vec3& v2) const;
240     /** Multiply operator */
241     inline constexpr Vec3& operator*=(const Vec3& rhs);
242 
243     /** Divide operator */
244     inline constexpr Vec3 operator/(const Vec3& v2) const;
245     /** Divide operator */
246     inline constexpr Vec3& operator/=(const Vec3& rhs);
247 
248     // Equality operators
249     /** Equality operator, returns true if the vectors are equal */
250     constexpr bool operator==(const Vec3& rhs) const;
251 
252     /** Inequality operator, returns true if vectors are inequal */
253     constexpr bool operator!=(const Vec3& rhs) const;
254 
255     // Vec3 to float operations
256     /** Multiplies vector by float value */
257     inline constexpr Vec3 operator*(float d) const;
258     /** Multiplies vector by float value */
259     inline constexpr Vec3& operator*=(float d);
260 
261     /** Divides vector by float value */
262     inline constexpr Vec3 operator/(float d) const;
263     /** Divides vector by float value */
264     inline constexpr Vec3& operator/=(float d);
265 };
266 
267 // Assert that Vec3 is the same as 3 floats
268 static_assert(sizeof(Vec3) == 3 * sizeof(float));
269 
270 /** @ingroup group_math_vector */
271 /** Vector4 presentation */
272 class Vec4 final {
273 public:
274     union {
275         struct {
276             float x;
277             float y;
278             float z;
279             float w;
280         };
281         float data[4];
282 #if defined(BASE_SIMD) && defined(_M_X64)
283         __m128 vec4;
284 #elif defined(_M_ARM64) || defined(__ARM_ARCH_ISA_A64)
285         float32x4_t vec4;
286 #endif
287     };
288     /** Subscript operator */
289     constexpr float& operator[](size_t index);
290     /** Subscript operator */
291     constexpr const float& operator[](size_t index) const;
292 
293     // Constructors
294     /** Default constructor */
295     inline constexpr Vec4() noexcept;
296     /** Constructor for using floats as input */
297     inline constexpr Vec4(float xParameter, float yParameter, float zParameter, float wParameter) noexcept;
298     /** Constructor for using array of floats as input */
299     inline constexpr Vec4(const float d[4]) noexcept;
300     /** Constructor for using vector3 and float as input (float as w component) */
301     inline constexpr Vec4(const Vec3& vec, float w) noexcept;
302     ~Vec4() = default;
303 
304     /** Add operator */
305     inline constexpr Vec4 operator+(const Vec4& v2) const;
306     /** Add operator */
307     inline constexpr Vec4& operator+=(const Vec4& rhs);
308 
309     /** Negate operator */
310     inline constexpr Vec4 operator-() const;
311 
312     /** Subtract operator */
313     inline constexpr Vec4 operator-(const Vec4& v2) const;
314     /** Subtract operator */
315     inline constexpr Vec4& operator-=(const Vec4& rhs);
316 
317     /** Multiply operator */
318     inline constexpr Vec4 operator*(const Vec4& v2) const;
319     /** Multiply operator */
320     inline constexpr Vec4& operator*=(const Vec4& rhs);
321 
322     /** Divide operator */
323     inline constexpr Vec4 operator/(const Vec4& v2) const;
324     /** Divide operator */
325     inline constexpr Vec4& operator/=(const Vec4& rhs);
326 
327     /** Multiplies a vector by a float value */
328     inline constexpr Vec4 operator*(float d) const;
329     /** Multiplies a vector by a float value */
330     inline constexpr Vec4& operator*=(float d);
331 
332     /** Divides a vector by a float value */
333     inline constexpr Vec4 operator/(float d) const;
334     /** Divides a vector by a float value */
335     inline constexpr Vec4& operator/=(float d);
336 
337     // Equality operators
338     /** Equality operator, returns true if the vectors are equal */
339     constexpr bool operator==(const Vec4& rhs) const;
340 
341     /** Inequality operator, returns true if vectors are different */
342     constexpr bool operator!=(const Vec4& rhs) const;
343 };
344 
345 // Assert that Vec4 is the same as 4 floats
346 static_assert(sizeof(Vec4) == 4 * sizeof(float));
347 
348 /** @ingroup group_math_vector */
349 /** Unsigned integer vector2 presentation */
350 class UVec2 final {
351 public:
352     union {
353         struct {
354             uint32_t x;
355             uint32_t y;
356         };
357         uint32_t data[2];
358     };
359 
360     /** Subscript operator */
361     constexpr uint32_t& operator[](size_t index)
362     {
363         return data[index];
364     }
365     /** Subscript operator */
366     constexpr const uint32_t& operator[](size_t index) const
367     {
368         return data[index];
369     }
370 
371     // Constructors
372     /** Default constructor */
373     inline constexpr UVec2() : data {} {}
374     /** Constructor for using two uint32_t's as input */
375     inline constexpr UVec2(uint32_t xParameter, uint32_t yParameter) : x(xParameter), y(yParameter) {}
376     ~UVec2() = default;
377 
378     /** Add operator */
379     inline constexpr UVec2 operator+(const UVec2& v2) const
380     {
381         return UVec2(x + v2.x, y + v2.y);
382     }
383     /** Add operator */
384     inline constexpr UVec2& operator+=(const UVec2& rhs)
385     {
386         x += rhs.x;
387         y += rhs.y;
388         return *this;
389     }
390 
391     /** Subtract operator */
392     inline constexpr UVec2 operator-(const UVec2& v2) const
393     {
394         return UVec2(x - v2.x, y - v2.y);
395     }
396     /** Subtract operator */
397     inline constexpr UVec2& operator-=(const UVec2& rhs)
398     {
399         x -= rhs.x;
400         y -= rhs.y;
401         return *this;
402     }
403 
404     /** Multiply operator */
405     inline constexpr UVec2 operator*(const UVec2& v2) const
406     {
407         return UVec2(x * v2.x, y * v2.y);
408     }
409     /** Multiply operator */
410     inline constexpr UVec2& operator*=(const UVec2& rhs)
411     {
412         x *= rhs.x;
413         y *= rhs.y;
414         return *this;
415     }
416 
417     /** Divide operator */
418     inline constexpr UVec2 operator/(const UVec2& v2) const
419     {
420         return UVec2(x / v2.x, y / v2.y);
421     }
422     /** Divide operator */
423     inline constexpr UVec2& operator/=(const UVec2& rhs)
424     {
425         x /= rhs.x;
426         y /= rhs.y;
427         return *this;
428     }
429 
430     /** Multiplies vector by float value */
431     inline constexpr UVec2 operator*(uint32_t d) const
432     {
433         return UVec2(x * d, y * d);
434     }
435     /** Multiplies vector by float value */
436     inline constexpr UVec2& operator*=(uint32_t d)
437     {
438         x *= d;
439         y *= d;
440         return *this;
441     }
442 
443     /** Divides vector by float value */
444     inline constexpr UVec2 operator/(uint32_t d) const
445     {
446         return UVec2(x / d, y / d);
447     }
448     /** Divides vector by float value */
449     inline constexpr UVec2& operator/=(uint32_t d)
450     {
451         if (d == 0) {
452             x = y = UINT32_MAX;
453             return *this;
454         }
455 
456         x /= d;
457         y /= d;
458         return *this;
459     }
460 
461     /** Subtract uint32_t from uvector2 */
462     inline constexpr UVec2 operator-(uint32_t d) const
463     {
464         return UVec2(x - d, y - d);
465     }
466     /** Subtract uint32_t from uvector2 */
467     inline constexpr UVec2& operator-=(uint32_t d)
468     {
469         x -= d;
470         y -= d;
471         return *this;
472     }
473 
474     /** Equality operator, returns true if the vectors are equal */
475     constexpr bool operator==(const UVec2& rhs) const
476     {
477         if (x != rhs.x) {
478             return false;
479         }
480         if (y != rhs.y) {
481             return false;
482         }
483         return true;
484     }
485 
486     /** Inequality operator, returns true if vectors are different */
487     constexpr bool operator!=(const UVec2& rhs) const
488     {
489         // Returns true in the presence of NaN values
490         return !(*this == rhs);
491     }
492 };
493 
494 // Assert that UVec2 is the same as 2 uint32_t's
495 static_assert(sizeof(UVec2) == 2 * sizeof(uint32_t));
496 
497 /** @ingroup group_math_vector */
498 /** Unsigned integer vector3 presentation */
499 class UVec3 {
500 public:
501     union {
502         struct {
503             uint32_t x;
504             uint32_t y;
505             uint32_t z;
506         };
507         uint32_t data[3];
508     };
509 
510     // Constructors
511     /** Default constructor */
512     inline constexpr UVec3() : data {} {}
513     /** Constructor for using three uint32_t's as input */
514     inline constexpr UVec3(uint32_t x, uint32_t y, uint32_t z) : x(x), y(y), z(z) {}
515     ~UVec3() = default;
516 
517     /** Subscript operator */
518     constexpr uint32_t& operator[](size_t index)
519     {
520         return data[index];
521     }
522 
523     /** Subscript operator */
524     constexpr const uint32_t& operator[](size_t index) const
525     {
526         return data[index];
527     }
528 
529     /** Equality operator, returns true if the vectors are equal */
530     constexpr bool operator==(const UVec3& rhs) const
531     {
532         if (x != rhs.x) {
533             return false;
534         }
535         if (y != rhs.y) {
536             return false;
537         }
538         if (z != rhs.z) {
539             return false;
540         }
541         return true;
542     }
543 
544     /** Inequality operator, returns true if vectors are different */
545     constexpr bool operator!=(const UVec3& rhs) const
546     {
547         // Returns true in the presence of NaN values
548         return !(*this == rhs);
549     }
550 };
551 
552 // Assert that UVec3 is the same as 3 uint32_t's
553 static_assert(sizeof(UVec3) == 3 * sizeof(uint32_t));
554 
555 /** @ingroup group_math_vector */
556 /** Unsigned integer vector4 presentation */
557 class UVec4 {
558 public:
559     union {
560         struct {
561             uint32_t x;
562             uint32_t y;
563             uint32_t z;
564             uint32_t w;
565         };
566         uint32_t data[4];
567     };
568     // Constructors
569     /** Default constructor */
570     inline constexpr UVec4() : data {} {}
571     /** Constructor for using four uint32_t's as input */
572     inline constexpr UVec4(uint32_t x, uint32_t y, uint32_t z, uint32_t w) : x(x), y(y), z(z), w(w) {}
573     ~UVec4() = default;
574 
575     /** Subscript operator */
576     constexpr uint32_t& operator[](size_t index)
577     {
578         return data[index];
579     }
580 
581     /** Subscript operator */
582     constexpr const uint32_t& operator[](size_t index) const
583     {
584         return data[index];
585     }
586 
587     /** Equality operator, returns true if the vectors are equal */
588     constexpr bool operator==(const UVec4& rhs) const
589     {
590         if (x != rhs.x) {
591             return false;
592         }
593         if (y != rhs.y) {
594             return false;
595         }
596         if (z != rhs.z) {
597             return false;
598         }
599         if (w != rhs.w) {
600             return false;
601         }
602         return true;
603     }
604 
605     /** Inequality operator, returns true if vectors are different */
606     constexpr bool operator!=(const UVec4& rhs) const
607     {
608         // Returns true in the presence of NaN values
609         return !(*this == rhs);
610     }
611 };
612 
613 // Assert that UVec4 is the same as 4 uint32_t's
614 static_assert(sizeof(UVec4) == 4 * sizeof(uint32_t));
615 
616 /** @ingroup group_math_vector */
617 /** Signed integer vector2 presentation */
618 class IVec2 final {
619 public:
620     union {
621         struct {
622             int32_t x;
623             int32_t y;
624         };
625         int32_t data[2];
626     };
627 
628     /** Subscript operator */
629     constexpr int32_t& operator[](size_t index)
630     {
631         return data[index];
632     }
633     /** Subscript operator */
634     constexpr const int32_t& operator[](size_t index) const
635     {
636         return data[index];
637     }
638 
639     // Constructors
640     /** Default constructor */
641     inline constexpr IVec2() : data {} {}
642     /** Constructor for using two int32_t's as input */
643     inline constexpr IVec2(int32_t xParameter, int32_t yParameter) : x(xParameter), y(yParameter) {}
644     ~IVec2() = default;
645 
646     /** Add operator */
647     inline constexpr IVec2 operator+(const IVec2& v2) const
648     {
649         return IVec2(x + v2.x, y + v2.y);
650     }
651     /** Add operator */
652     inline constexpr IVec2& operator+=(const IVec2& rhs)
653     {
654         x += rhs.x;
655         y += rhs.y;
656         return *this;
657     }
658 
659     /** Subtract operator */
660     inline constexpr IVec2 operator-(const IVec2& v2) const
661     {
662         return IVec2(x - v2.x, y - v2.y);
663     }
664     /** Subtract operator */
665     inline constexpr IVec2& operator-=(const IVec2& rhs)
666     {
667         x -= rhs.x;
668         y -= rhs.y;
669         return *this;
670     }
671 
672     /** Multiply operator */
673     inline constexpr IVec2 operator*(const IVec2& v2) const
674     {
675         return IVec2(x * v2.x, y * v2.y);
676     }
677     /** Multiply operator */
678     inline constexpr IVec2& operator*=(const IVec2& rhs)
679     {
680         x *= rhs.x;
681         y *= rhs.y;
682         return *this;
683     }
684 
685     /** Divide operator */
686     inline constexpr IVec2 operator/(const IVec2& v2) const
687     {
688         return IVec2(x / v2.x, y / v2.y);
689     }
690     /** Divide operator */
691     inline constexpr IVec2& operator/=(const IVec2& rhs)
692     {
693         x /= rhs.x;
694         y /= rhs.y;
695         return *this;
696     }
697 
698     /** Multiplies vector by float value */
699     inline constexpr IVec2 operator*(int32_t d) const
700     {
701         return IVec2(x * d, y * d);
702     }
703     /** Multiplies vector by float value */
704     inline constexpr IVec2& operator*=(int32_t d)
705     {
706         x *= d;
707         y *= d;
708         return *this;
709     }
710 
711     /** Divides vector by float value */
712     inline constexpr IVec2 operator/(int32_t d) const
713     {
714         return IVec2(x / d, y / d);
715     }
716     /** Divides vector by float value */
717     inline constexpr IVec2& operator/=(int32_t d)
718     {
719         if (d == 0) {
720             x = y = INT32_MAX;
721             return *this;
722         }
723 
724         x /= d;
725         y /= d;
726         return *this;
727     }
728 
729     /** Subtract int32_t from IVector2 */
730     inline constexpr IVec2 operator-(int32_t d) const
731     {
732         return IVec2(x - d, y - d);
733     }
734     /** Subtract int32_t from IVector2 */
735     inline constexpr IVec2& operator-=(int32_t d)
736     {
737         x -= d;
738         y -= d;
739         return *this;
740     }
741 
742     /** Equality operator, returns true if the vectors are equal */
743     constexpr bool operator==(const IVec2& rhs) const
744     {
745         if (x != rhs.x) {
746             return false;
747         }
748         if (y != rhs.y) {
749             return false;
750         }
751         return true;
752     }
753 
754     /** Inequality operator, returns true if vectors are different */
755     constexpr bool operator!=(const IVec2& rhs) const
756     {
757         // Returns true in the presence of NaN values
758         return !(*this == rhs);
759     }
760 };
761 
762 // Assert that IVec2 is the same as 2 int32_t's
763 static_assert(sizeof(IVec2) == 2 * sizeof(int32_t));
764 
765 /** @ingroup group_math_vector */
766 /** Signed integer vector3 presentation */
767 class IVec3 {
768 public:
769     union {
770         struct {
771             int32_t x;
772             int32_t y;
773             int32_t z;
774         };
775         int32_t data[3];
776     };
777 
778     // Constructors
779     /** Default constructor */
780     inline constexpr IVec3() : data {} {}
781     /** Constructor for using three int32_t's as input */
782     inline constexpr IVec3(int32_t x, int32_t y, int32_t z) : x(x), y(y), z(z) {}
783     ~IVec3() = default;
784 
785     /** Subscript operator */
786     constexpr int32_t& operator[](size_t index)
787     {
788         return data[index];
789     }
790 
791     /** Subscript operator */
792     constexpr const int32_t& operator[](size_t index) const
793     {
794         return data[index];
795     }
796 
797     /** Equality operator, returns true if the vectors are equal */
798     constexpr bool operator==(const IVec3& rhs) const
799     {
800         if (x != rhs.x) {
801             return false;
802         }
803         if (y != rhs.y) {
804             return false;
805         }
806         if (z != rhs.z) {
807             return false;
808         }
809         return true;
810     }
811 
812     /** Inequality operator, returns true if vectors are different */
813     constexpr bool operator!=(const IVec3& rhs) const
814     {
815         // Returns true in the presence of NaN values
816         return !(*this == rhs);
817     }
818 };
819 
820 // Assert that IVec3 is the same as 3 int32_t's
821 static_assert(sizeof(IVec3) == 3 * sizeof(int32_t));
822 
823 /** @ingroup group_math_vector */
824 /** Signed integer vector4 presentation */
825 class IVec4 {
826 public:
827     union {
828         struct {
829             int32_t x;
830             int32_t y;
831             int32_t z;
832             int32_t w;
833         };
834         int32_t data[4];
835     };
836     // Constructors
837     /** Default constructor */
838     inline constexpr IVec4() : data {} {}
839     /** Constructor for using four int32_t's as input */
840     inline constexpr IVec4(int32_t x, int32_t y, int32_t z, int32_t w) : x(x), y(y), z(z), w(w) {}
841     ~IVec4() = default;
842 
843     /** Subscript operator */
844     constexpr int32_t& operator[](size_t index)
845     {
846         return data[index];
847     }
848 
849     /** Subscript operator */
850     constexpr const int32_t& operator[](size_t index) const
851     {
852         return data[index];
853     }
854 
855     /** Equality operator, returns true if the vectors are equal */
856     constexpr bool operator==(const IVec4& rhs) const
857     {
858         if (x != rhs.x) {
859             return false;
860         }
861         if (y != rhs.y) {
862             return false;
863         }
864         if (z != rhs.z) {
865             return false;
866         }
867         if (w != rhs.w) {
868             return false;
869         }
870         return true;
871     }
872 
873     /** Inequality operator, returns true if vectors are different */
874     constexpr bool operator!=(const IVec4& rhs) const
875     {
876         // Returns true in the presence of NaN values
877         return !(*this == rhs);
878     }
879 };
880 
881 // Assert that IVec4 is the same as 4 int32_t's
882 static_assert(sizeof(IVec4) == 4 * sizeof(int32_t));
883 
884 constexpr float& Vec3::operator[](size_t index)
885 {
886     return data[index];
887 }
888 constexpr const float& Vec3::operator[](size_t index) const
889 {
890     return data[index];
891 }
892 
893 // Constructors
894 inline constexpr Vec3::Vec3() noexcept : data {} {}
895 inline constexpr Vec3::Vec3(float xParameter, float yParameter, float zParameter) noexcept
896     : x(xParameter), y(yParameter), z(zParameter)
897 {}
898 inline constexpr Vec3::Vec3(const float d[]) noexcept : x(d[0]), y(d[1]), z(d[2]) {}
899 inline constexpr Vec3::Vec3(const Vec4& vec) noexcept : x(vec.x), y(vec.y), z(vec.z) {}
900 
901 // Vec3 to Vec3 operations
902 // Add
903 inline constexpr Vec3 Vec3::operator+(const Vec3& v2) const
904 {
905     return Vec3(x + v2.x, y + v2.y, z + v2.z);
906 }
907 // Add
908 inline constexpr Vec3& Vec3::operator+=(const Vec3& rhs)
909 {
910     x += rhs.x;
911     y += rhs.y;
912     z += rhs.z;
913     return *this;
914 }
915 
916 // Negate
917 inline constexpr Vec3 Vec3::operator-() const
918 {
919     return Vec3(-x, -y, -z);
920 }
921 
922 // Subtract
923 inline constexpr Vec3 Vec3::operator-(const Vec3& v2) const
924 {
925     return Vec3(x - v2.x, y - v2.y, z - v2.z);
926 }
927 // Subtract
928 inline constexpr Vec3& Vec3::operator-=(const Vec3& rhs)
929 {
930     x -= rhs.x;
931     y -= rhs.y;
932     z -= rhs.z;
933     return *this;
934 }
935 
936 // Multiply
937 inline constexpr Vec3 Vec3::operator*(const Vec3& v2) const
938 {
939     return Vec3(x * v2.x, y * v2.y, z * v2.z);
940 }
941 // Multiply
942 inline constexpr Vec3& Vec3::operator*=(const Vec3& rhs)
943 {
944     x *= rhs.x;
945     y *= rhs.y;
946     z *= rhs.z;
947     return *this;
948 }
949 
950 // Divide
951 inline constexpr Vec3 Vec3::operator/(const Vec3& v2) const
952 {
953     return Vec3(x / v2.x, y / v2.y, z / v2.z);
954 }
955 // Divide
956 inline constexpr Vec3& Vec3::operator/=(const Vec3& rhs)
957 {
958     x /= rhs.x;
959     y /= rhs.y;
960     z /= rhs.z;
961     return *this;
962 }
963 
964 // Equality operators
965 // Returns true if the vectors are equal
966 constexpr bool Vec3::operator==(const Vec3& rhs) const
967 {
968     const Vec3 temp = *this - rhs;
969     const float sqmgt = temp.x * temp.x + temp.y * temp.y + temp.z * temp.z;
970 
971     // Returns false in the presence of NaN values
972     return sqmgt < Math::EPSILON * Math::EPSILON;
973 }
974 
975 // Returns true if vectors are different.
976 constexpr bool Vec3::operator!=(const Vec3& rhs) const
977 {
978     // Returns true in the presence of NaN values
979     return !(*this == rhs);
980 }
981 
982 // Vec3 to float operations
983 // Multiplies vector by float value
984 inline constexpr Vec3 Vec3::operator*(float d) const
985 {
986     return Vec3(x * d, y * d, z * d);
987 }
988 inline constexpr Vec3& Vec3::operator*=(float d)
989 {
990     x *= d;
991     y *= d;
992     z *= d;
993     return *this;
994 }
995 
996 // Divides vector by float value
997 inline constexpr Vec3 Vec3::operator/(float d) const
998 {
999     return Vec3(x / d, y / d, z / d);
1000 }
1001 inline constexpr Vec3& Vec3::operator/=(float d)
1002 {
1003     x /= d;
1004     y /= d;
1005     z /= d;
1006     return *this;
1007 }
1008 
1009 constexpr float& Vec4::operator[](size_t index)
1010 {
1011     return data[index];
1012 }
1013 constexpr const float& Vec4::operator[](size_t index) const
1014 {
1015     return data[index];
1016 }
1017 
1018 static constexpr Vec3 ZERO_VEC3(0.0f, 0.0f, 0.0f);
1019 
1020 // Constructors
1021 inline constexpr Vec4::Vec4() noexcept : data {} {}
1022 inline constexpr Vec4::Vec4(float xParameter, float yParameter, float zParameter, float wParameter) noexcept
1023     : x(xParameter), y(yParameter), z(zParameter), w(wParameter)
1024 {}
1025 inline constexpr Vec4::Vec4(const float d[4]) noexcept : x(d[0]), y(d[1]), z(d[2]), w(d[3]) {}
1026 inline constexpr Vec4::Vec4(const Vec3& vec, float w) noexcept : x(vec.x), y(vec.y), z(vec.z), w(w) {}
1027 
1028 // Add
1029 inline constexpr Vec4 Vec4::operator+(const Vec4& v2) const
1030 {
1031     return Vec4(x + v2.x, y + v2.y, z + v2.z, w + v2.w);
1032 }
1033 
1034 inline constexpr Vec4& Vec4::operator+=(const Vec4& rhs)
1035 {
1036     x += rhs.x;
1037     y += rhs.y;
1038     z += rhs.z;
1039     w += rhs.w;
1040     return *this;
1041 }
1042 
1043 // Negate
1044 inline constexpr Vec4 Vec4::operator-() const
1045 {
1046     return Vec4(-x, -y, -z, -w);
1047 }
1048 
1049 // Subtract
1050 inline constexpr Vec4 Vec4::operator-(const Vec4& v2) const
1051 {
1052     return Vec4(x - v2.x, y - v2.y, z - v2.z, w - v2.w);
1053 }
1054 
1055 inline constexpr Vec4& Vec4::operator-=(const Vec4& rhs)
1056 {
1057     x -= rhs.x;
1058     y -= rhs.y;
1059     z -= rhs.z;
1060     w -= rhs.w;
1061     return *this;
1062 }
1063 
1064 // Multiply
1065 inline constexpr Vec4 Vec4::operator*(const Vec4& v2) const
1066 {
1067     return Vec4(x * v2.x, y * v2.y, z * v2.z, w * v2.w);
1068 }
1069 
1070 inline constexpr Vec4& Vec4::operator*=(const Vec4& rhs)
1071 {
1072     x *= rhs.x;
1073     y *= rhs.y;
1074     z *= rhs.z;
1075     w *= rhs.w;
1076     return *this;
1077 }
1078 
1079 // Divide
1080 inline constexpr Vec4 Vec4::operator/(const Vec4& v2) const
1081 {
1082     return Vec4(x / v2.x, y / v2.y, z / v2.z, w / v2.w);
1083 }
1084 
1085 inline constexpr Vec4& Vec4::operator/=(const Vec4& rhs)
1086 {
1087     x /= rhs.x;
1088     y /= rhs.y;
1089     z /= rhs.z;
1090     w /= rhs.w;
1091     return *this;
1092 }
1093 
1094 // Multiplies a vector by a float value
1095 inline constexpr Vec4 Vec4::operator*(float d) const
1096 {
1097     return Vec4(x * d, y * d, z * d, w * d);
1098 }
1099 inline constexpr Vec4& Vec4::operator*=(float d)
1100 {
1101     x *= d;
1102     y *= d;
1103     z *= d;
1104     w *= d;
1105     return *this;
1106 }
1107 
1108 // Divides a vector by a float value
1109 inline constexpr Vec4 Vec4::operator/(float d) const
1110 {
1111     return Vec4(x / d, y / d, z / d, w / d);
1112 }
1113 inline constexpr Vec4& Vec4::operator/=(float d)
1114 {
1115     x /= d;
1116     y /= d;
1117     z /= d;
1118     w /= d;
1119     return *this;
1120 }
1121 
1122 // Equality operators
1123 // Returns true if the vectors are equal.
1124 constexpr bool Vec4::operator==(const Vec4& rhs) const
1125 {
1126     const Vec4 temp = *this - rhs;
1127     const float sqmgt = temp.x * temp.x + temp.y * temp.y + temp.z * temp.z + temp.w * temp.w;
1128 
1129     // Returns false in the presence of NaN values
1130     return sqmgt < Math::EPSILON * Math::EPSILON;
1131 }
1132 
1133 // Returns true if vectors are different.
1134 constexpr bool Vec4::operator!=(const Vec4& rhs) const
1135 {
1136     // Returns true in the presence of NaN values
1137     return !(*this == rhs);
1138 }
1139 
1140 static constexpr Vec4 ZERO_VEC4(0.0f, 0.0f, 0.0f, 0.0f);
1141 
1142 #include <base/math/disable_warning_4201_footer.h>
1143 } // namespace Math
1144 BASE_END_NAMESPACE()
1145 
1146 #endif // API_BASE_MATH_VECTOR_H
1147