1 // Copyright Google Inc. All Rights Reserved.
2 //
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 // Simple classes to handle vectors in 2D, 3D, and 4D.
17 //
18 // Maintainers: Please be mindful of extreme degradations in unoptimized
19 // performance here.
20 #ifndef S2_UTIL_MATH_VECTOR_H_
21 #define S2_UTIL_MATH_VECTOR_H_
22 
23 #include <algorithm>
24 #include <cmath>
25 #include <cstdlib>
26 #include <iosfwd>
27 #include <iostream>  // NOLINT(readability/streams)
28 #include <limits>
29 #include <type_traits>
30 
31 #include "s2/base/integral_types.h"
32 #include "s2/base/logging.h"
33 #include "s2/third_party/absl/base/macros.h"
34 #include "s2/third_party/absl/utility/utility.h"
35 
36 template <typename T> class Vector2;
37 template <typename T> class Vector3;
38 template <typename T> class Vector4;
39 
40 namespace util {
41 namespace math {
42 namespace internal_vector {
43 
44 // CRTP base class for all Vector templates.
45 template <template <typename> class VecTemplate, typename T, std::size_t N>
46 class BasicVector {
47   using D = VecTemplate<T>;
48 
49  protected:
50   // FloatType is the type returned by Norm() and Angle().  These methods are
51   // special because they return floating-point values even when VType is an
52   // integer.
53   typedef typename std::conditional<std::is_integral<T>::value,
54                                     double, T>::type FloatType;
55 
56   using IdxSeqN = typename absl::make_index_sequence<N>;
57 
58   template <std::size_t I, typename F, typename... As>
59   static auto Reduce(F f, As*... as)
60       -> decltype(f(as[I]...)) {
61     return f(as[I]...);
62   }
63 
64   template <typename R = D, std::size_t... Is, typename F, typename... As>
GenerateEach(absl::index_sequence<Is...>,F f,As * ...as)65   static R GenerateEach(absl::index_sequence<Is...>, F f, As*... as) {
66     return R(Reduce<Is>(f, as...)...);
67   }
68 
69   // Generate<R>(f,a,b,...) returns an R(...), where the constructor arguments
70   // are created as a transform. R(f(a[0],b[0],...), f(a[1],b[1],...), ...),
71   // and with a,b,...  all optional.
72   template <typename R = D, typename F, typename... As>
Generate(F f,As &&...as)73   static R Generate(F f, As&&... as) {
74     return GenerateEach<R>(IdxSeqN(), f, std::forward<As>(as).Data()...);
75   }
76 
77  public:
78   enum { SIZE = N };
Size()79   static int Size() { return SIZE; }
80 
Clear()81   void Clear() { AsD() = D(); }
82 
83   T& operator[](int b) {
84     S2_DCHECK_GE(b, 0);
85     S2_DCHECK_LT(b, SIZE);
86     return static_cast<D&>(*this).Data()[b];
87   }
88   T operator[](int b) const {
89     S2_DCHECK_GE(b, 0);
90     S2_DCHECK_LT(b, SIZE);
91     return static_cast<const D&>(*this).Data()[b];
92   }
93 
94   // TODO(user): Relationals should be nonmembers.
95   bool operator==(const D& b) const {
96     const T* ap = static_cast<const D&>(*this).Data();
97     return std::equal(ap, ap + this->Size(), b.Data());
98   }
99   bool operator!=(const D& b) const { return !(AsD() == b); }
100   bool operator<(const D& b) const {
101     const T* ap = static_cast<const D&>(*this).Data();
102     const T* bp = b.Data();
103     return std::lexicographical_compare(
104         ap, ap + this->Size(), bp, bp + b.Size());
105   }
106   bool operator>(const D& b) const { return b < AsD(); }
107   bool operator<=(const D& b) const { return !(AsD() > b); }
108   bool operator>=(const D& b) const { return !(AsD() < b); }
109 
110   D& operator+=(const D& b) {
111     PlusEq(static_cast<D&>(*this).Data(), b.Data(), IdxSeqN{});
112     return static_cast<D&>(*this);
113   }
114 
115   D& operator-=(const D& b) {
116     MinusEq(static_cast<D&>(*this).Data(), b.Data(), IdxSeqN{});
117     return static_cast<D&>(*this);
118   }
119 
120   D& operator*=(T k) {
121     MulEq(static_cast<D&>(*this).Data(), k, IdxSeqN{});
122     return static_cast<D&>(*this);
123   }
124 
125   D& operator/=(T k) {
126     DivEq(static_cast<D&>(*this).Data(), k, IdxSeqN{});
127     return static_cast<D&>(*this);
128   }
129 
130   D operator+(const D& b) const { return D(AsD()) += b; }
131   D operator-(const D& b) const { return D(AsD()) -= b; }
132   D operator*(T k) const { return D(AsD()) *= k; }
133   D operator/(T k) const { return D(AsD()) /= k; }
134 
135   friend D operator-(const D& a) {
136     return Generate([](const T& x) { return -x; }, a);
137   }
138 
139   // Convert from another vector type
140   template <typename T2>
Cast(const VecTemplate<T2> & b)141   static D Cast(const VecTemplate<T2> &b) {
142     return Generate([](const T2& x) { return static_cast<T>(x); }, b);
143   }
144 
145   // multiply two vectors component by component
MulComponents(const D & b)146   D MulComponents(const D &b) const {
147     return Generate([](const T& x, const T& y) { return x * y; }, AsD(), b);
148   }
149   // divide two vectors component by component
DivComponents(const D & b)150   D DivComponents(const D &b) const {
151     return Generate([](const T& x, const T& y) { return x / y; }, AsD(), b);
152   }
153 
154   // Element-wise max.  {max(a[0],b[0]), max(a[1],b[1]), ...}
Max(const D & a,const D & b)155   friend D Max(const D &a, const D &b) {
156     return Generate([](const T& x, const T& y) {
157       return std::max(x, y);
158     }, a, b);
159   }
160 
161   // Element-wise min.  {min(a[0],b[0]), min(a[1],b[1]), ...}
Min(const D & a,const D & b)162   friend D Min(const D &a, const D &b) {
163     return Generate([](const T& x, const T& y) {
164       return std::min(x, y);
165     }, a, b);
166   }
167 
DotProd(const D & b)168   T DotProd(const D& b) const {
169     return Dot(static_cast<T>(0), static_cast<const D&>(*this).Data(), b.Data(),
170                IdxSeqN{});
171   }
172 
173   // Squared Euclidean norm (the dot product with itself).
Norm2()174   T Norm2() const { return DotProd(AsD()); }
175 
176   // Euclidean norm. For integer T, correct only if Norm2 does not overflow.
Norm()177   FloatType Norm() const {
178     using std::sqrt;
179     return sqrt(Norm2());
180   }
181 
182   // Normalized vector if the norm is nonzero. Not for integer types.
Normalize()183   D Normalize() const {
184     static_assert(!std::is_integral<T>::value, "must be floating point");
185     T n = Norm();
186     if (n != T(0.0)) {
187       n = T(1.0) / n;
188     }
189     return D(AsD()) *= n;
190   }
191 
192   // Compose a vector from the sqrt of each component.
Sqrt()193   D Sqrt() const {
194     return Generate([](const T& x) {
195       using std::sqrt;
196       return sqrt(x);
197     }, AsD());
198   }
199 
200   // Take the floor of each component.
Floor()201   D Floor() const {
202     return Generate([](const T& x) { return floor(x); }, AsD());
203   }
204 
205   // Take the ceil of each component.
Ceil()206   D Ceil() const {
207     return Generate([](const T& x) { return ceil(x); }, AsD());
208   }
209 
210   // Round of each component.
FRound()211   D FRound() const {
212     using std::rint;
213     return Generate([](const T& x) { return rint(x); }, AsD());
214   }
215 
216   // Round of each component and return an integer vector.
IRound()217   VecTemplate<int> IRound() const {
218     using std::lrint;
219     return Generate<VecTemplate<int>>([](const T& x) { return lrint(x); },
220                                       AsD());
221   }
222 
223   // True if any of the components is not a number.
IsNaN()224   bool IsNaN() const {
225     bool r = false;
226     const T* ap = AsD().Data();
227     for (int i = 0; i < SIZE; ++i)
228       r = r || isnan(ap[i]);
229     return r;
230   }
231 
232   // A Vector populated with all NaN values.
NaN()233   static D NaN() {
234     return Generate([] { return std::numeric_limits<T>::quiet_NaN(); });
235   }
236 
237   friend std::ostream& operator<<(std::ostream& out, const D& v) {
238     out << "[";
239     const char *sep = "";
240     for (int i = 0; i < SIZE; ++i) {
241       out << sep;
242       Print(out, v[i]);
243       sep = ", ";
244     }
245     return out << "]";
246   }
247 
248   // These are only public for technical reasons (see cl/121145822).
249   template <typename K>
MulScalarInternal(const K & k)250   D MulScalarInternal(const K& k) const {
251     return Generate([k](const T& x) { return k * x; }, AsD());
252   }
253   template <typename K>
DivScalarInternal(const K & k)254   D DivScalarInternal(const K& k) const {
255     return Generate([k](const T& x) { return k / x; }, AsD());
256   }
257 
258  private:
AsD()259   const D& AsD() const { return static_cast<const D&>(*this); }
AsD()260   D& AsD() { return static_cast<D&>(*this); }
261 
262   // ostream << uint8 prints the ASCII character, which is not useful.
263   // Cast to int so that numbers will be printed instead.
264   template <typename U>
Print(std::ostream & out,const U & v)265   static void Print(std::ostream& out, const U& v) { out << v; }
Print(std::ostream & out,uint8 v)266   static void Print(std::ostream& out, uint8 v) { out << static_cast<int>(v); }
267 
268   // Ignores its arguments so that side-effects of variadic unpacking can occur.
Ignore(std::initializer_list<bool>)269   static void Ignore(std::initializer_list<bool>) {}
270 
271   template <std::size_t... Is>
Dot(T sum,const T * a,const T * b,absl::index_sequence<Is...>)272   static T Dot(T sum, const T* a, const T* b, absl::index_sequence<Is...>) {
273     Ignore({(sum += a[Is] * b[Is], true)...});
274     return sum;
275   }
276 
277   template <std::size_t... Is>
PlusEq(T * a,const T * b,absl::index_sequence<Is...>)278   static void PlusEq(T* a, const T* b, absl::index_sequence<Is...>) {
279     Ignore({(a[Is] += b[Is], true)...});
280   }
281 
282   template <std::size_t... Is>
MinusEq(T * a,const T * b,absl::index_sequence<Is...>)283   static void MinusEq(T* a, const T* b, absl::index_sequence<Is...>) {
284     Ignore({(a[Is] -= b[Is], true)...});
285   }
286 
287   template <std::size_t... Is>
MulEq(T * a,T b,absl::index_sequence<Is...>)288   static void MulEq(T* a, T b, absl::index_sequence<Is...>) {
289     Ignore({(a[Is] *= b, true)...});
290   }
291 
292   template <std::size_t... Is>
DivEq(T * a,T b,absl::index_sequence<Is...>)293   static void DivEq(T* a, T b, absl::index_sequence<Is...>) {
294     Ignore({(a[Is] /= b, true)...});
295   }
296 };
297 
298 // These templates must be defined outside of BasicVector so that the
299 // template specialization match algorithm must deduce 'a'. See the review
300 // of cl/119944115.
301 template <typename K,
302           template <typename> class VT2, typename T2, std::size_t N2>
303 VT2<T2> operator*(const K& k, const BasicVector<VT2, T2, N2>& a) {
304   return a.MulScalarInternal(k);
305 }
306 template <typename K,
307           template <typename> class VT2, typename T2, std::size_t N2>
308 VT2<T2> operator/(const K& k, const BasicVector<VT2, T2, N2>& a) {
309   return a.DivScalarInternal(k);
310 }
311 
312 }  // namespace internal_vector
313 }  // namespace math
314 }  // namespace util
315 
316 // ======================================================================
317 template <typename T>
318 class Vector2
319     : public util::math::internal_vector::BasicVector<Vector2, T, 2> {
320  private:
321   using Base = util::math::internal_vector::BasicVector<::Vector2, T, 2>;
322   using VType = T;
323 
324  public:
325   typedef VType BaseType;
326   using FloatType = typename Base::FloatType;
327   using Base::SIZE;
328 
Vector2()329   Vector2() : c_() {}
Vector2(T x,T y)330   Vector2(T x, T y) {
331     c_[0] = x;
332     c_[1] = y;
333   }
Vector2(const Vector3<T> & b)334   explicit Vector2(const Vector3<T> &b) : Vector2(b.x(), b.y()) {}
Vector2(const Vector4<T> & b)335   explicit Vector2(const Vector4<T> &b) : Vector2(b.x(), b.y()) {}
336 
Data()337   T* Data() { return c_; }
Data()338   const T* Data() const { return c_; }
339 
x(T v)340   void x(T v) { c_[0] = v; }
y(T v)341   void y(T v) { c_[1] = v; }
x()342   T x() const { return c_[0]; }
y()343   T y() const { return c_[1]; }
344 
aequal(const Vector2 & vb,FloatType margin)345   bool aequal(const Vector2 &vb, FloatType margin) const {
346     using std::fabs;
347     return (fabs(c_[0]-vb.c_[0]) < margin) && (fabs(c_[1]-vb.c_[1]) < margin);
348   }
349 
Set(T x,T y)350   void Set(T x, T y) { *this = Vector2(x, y); }
351 
352   // Cross product.  Be aware that if T is an integer type, the high bits
353   // of the result are silently discarded.
CrossProd(const Vector2 & vb)354   T CrossProd(const Vector2 &vb) const {
355     return c_[0] * vb.c_[1] - c_[1] * vb.c_[0];
356   }
357 
358   // Returns the angle between "this" and v in radians. If either vector is
359   // zero-length, or nearly zero-length, the result will be zero, regardless of
360   // the other value.
Angle(const Vector2 & v)361   FloatType Angle(const Vector2 &v) const {
362     using std::atan2;
363     return atan2(CrossProd(v), this->DotProd(v));
364   }
365 
366   // return a vector orthogonal to the current one
367   // with the same norm and counterclockwise to it
Ortho()368   Vector2 Ortho() const { return Vector2(-c_[1], c_[0]); }
369 
370   // TODO(user): unify Fabs/Abs between all Vector classes.
Fabs()371   Vector2 Fabs() const {
372     using std::fabs;
373     return Vector2(fabs(c_[0]), fabs(c_[1]));
374   }
Abs()375   Vector2 Abs() const {
376     static_assert(std::is_integral<VType>::value, "use Fabs for float_types");
377     static_assert(static_cast<VType>(-1) == -1, "type must be signed");
378     static_assert(sizeof(c_[0]) <= sizeof(int), "Abs truncates to int");
379     return Vector2(abs(c_[0]), abs(c_[1]));
380   }
381 
382  private:
383   VType c_[SIZE];
384 };
385 
386 template <typename T>
387 class Vector3
388     : public util::math::internal_vector::BasicVector<Vector3, T, 3> {
389  private:
390   using Base = util::math::internal_vector::BasicVector<::Vector3, T, 3>;
391   using VType = T;
392 
393  public:
394   typedef VType BaseType;
395   using FloatType = typename Base::FloatType;
396   using Base::SIZE;
397 
Vector3()398   Vector3() : c_() {}
Vector3(T x,T y,T z)399   Vector3(T x, T y, T z) {
400     c_[0] = x;
401     c_[1] = y;
402     c_[2] = z;
403   }
Vector3(const Vector2<T> & b,T z)404   Vector3(const Vector2<T> &b, T z) : Vector3(b.x(), b.y(), z) {}
Vector3(const Vector4<T> & b)405   explicit Vector3(const Vector4<T> &b) : Vector3(b.x(), b.y(), b.z()) {}
406 
Data()407   T* Data() { return c_; }
Data()408   const T* Data() const { return c_; }
409 
x(const T & v)410   void x(const T &v) { c_[0] = v; }
y(const T & v)411   void y(const T &v) { c_[1] = v; }
z(const T & v)412   void z(const T &v) { c_[2] = v; }
x()413   T x() const { return c_[0]; }
y()414   T y() const { return c_[1]; }
z()415   T z() const { return c_[2]; }
416 
aequal(const Vector3 & vb,FloatType margin)417   bool aequal(const Vector3 &vb, FloatType margin) const {
418     using std::abs;
419     return (abs(c_[0] - vb.c_[0]) < margin)
420         && (abs(c_[1] - vb.c_[1]) < margin)
421         && (abs(c_[2] - vb.c_[2]) < margin);
422   }
423 
Set(T x,T y,T z)424   void Set(T x, T y, T z) { *this = Vector3(x, y, z); }
425 
426   // Cross product.  Be aware that if VType is an integer type, the high bits
427   // of the result are silently discarded.
CrossProd(const Vector3 & vb)428   Vector3 CrossProd(const Vector3& vb) const {
429     return Vector3(c_[1] * vb.c_[2] - c_[2] * vb.c_[1],
430                    c_[2] * vb.c_[0] - c_[0] * vb.c_[2],
431                    c_[0] * vb.c_[1] - c_[1] * vb.c_[0]);
432   }
433 
434   // Returns a unit vector orthogonal to this one.
Ortho()435   Vector3 Ortho() const {
436     int k = LargestAbsComponent() - 1;
437     if (k < 0) k = 2;
438     Vector3 temp;
439     temp[k] = T(1);
440     return CrossProd(temp).Normalize();
441   }
442 
443   // Returns the angle between two vectors in radians. If either vector is
444   // zero-length, or nearly zero-length, the result will be zero, regardless of
445   // the other value.
Angle(const Vector3 & va)446   FloatType Angle(const Vector3 &va) const {
447     using std::atan2;
448     return atan2(CrossProd(va).Norm(), this->DotProd(va));
449   }
450 
Fabs()451   Vector3 Fabs() const {
452     return Abs();
453   }
454 
Abs()455   Vector3 Abs() const {
456     static_assert(
457         !std::is_integral<VType>::value || static_cast<VType>(-1) == -1,
458         "type must be signed");
459     using std::abs;
460     return Vector3(abs(c_[0]), abs(c_[1]), abs(c_[2]));
461   }
462 
463   // return the index of the largest component (fabs)
LargestAbsComponent()464   int LargestAbsComponent() const {
465     Vector3 temp = Abs();
466     return temp[0] > temp[1] ?
467              temp[0] > temp[2] ? 0 : 2 :
468              temp[1] > temp[2] ? 1 : 2;
469   }
470 
471   // return the index of the smallest, median ,largest component of the vector
ComponentOrder()472   Vector3<int> ComponentOrder() const {
473     using std::swap;
474     Vector3<int> temp(0, 1, 2);
475     if (c_[temp[0]] > c_[temp[1]]) swap(temp[0], temp[1]);
476     if (c_[temp[1]] > c_[temp[2]]) swap(temp[1], temp[2]);
477     if (c_[temp[0]] > c_[temp[1]]) swap(temp[0], temp[1]);
478     return temp;
479   }
480 
481  private:
482   VType c_[SIZE];
483 };
484 
485 template <typename T>
486 class Vector4
487     : public util::math::internal_vector::BasicVector<Vector4, T, 4> {
488  private:
489   using Base = util::math::internal_vector::BasicVector<::Vector4, T, 4>;
490   using VType = T;
491 
492  public:
493   typedef VType BaseType;
494   using FloatType = typename Base::FloatType;
495   using Base::SIZE;
496 
Vector4()497   Vector4() : c_() {}
Vector4(T x,T y,T z,T w)498   Vector4(T x, T y, T z, T w) {
499     c_[0] = x;
500     c_[1] = y;
501     c_[2] = z;
502     c_[3] = w;
503   }
504 
Vector4(const Vector2<T> & b,T z,T w)505   Vector4(const Vector2<T> &b, T z, T w)
506       : Vector4(b.x(), b.y(), z, w) {}
Vector4(const Vector2<T> & a,const Vector2<T> & b)507   Vector4(const Vector2<T> &a, const Vector2<T> &b)
508       : Vector4(a.x(), a.y(), b.x(), b.y()) {}
Vector4(const Vector3<T> & b,T w)509   Vector4(const Vector3<T> &b, T w)
510       : Vector4(b.x(), b.y(), b.z(), w) {}
511 
Data()512   T* Data() { return c_; }
Data()513   const T* Data() const { return c_; }
514 
aequal(const Vector4 & vb,FloatType margin)515   bool aequal(const Vector4 &vb, FloatType margin) const {
516     using std::fabs;
517     return (fabs(c_[0] - vb.c_[0]) < margin)
518         && (fabs(c_[1] - vb.c_[1]) < margin)
519         && (fabs(c_[2] - vb.c_[2]) < margin)
520         && (fabs(c_[3] - vb.c_[3]) < margin);
521   }
522 
x(const T & v)523   void x(const T &v) { c_[0] = v; }
y(const T & v)524   void y(const T &v) { c_[1] = v; }
z(const T & v)525   void z(const T &v) { c_[2] = v; }
w(const T & v)526   void w(const T &v) { c_[3] = v; }
x()527   T x() const { return c_[0]; }
y()528   T y() const { return c_[1]; }
z()529   T z() const { return c_[2]; }
w()530   T w() const { return c_[3]; }
531 
Set(T x,T y,T z,T w)532   void Set(T x, T y, T z, T w) { *this = Vector4(x, y, z, w); }
533 
Fabs()534   Vector4 Fabs() const {
535     using std::fabs;
536     return Vector4(fabs(c_[0]), fabs(c_[1]), fabs(c_[2]), fabs(c_[3]));
537   }
538 
Abs()539   Vector4 Abs() const {
540     static_assert(std::is_integral<VType>::value, "use Fabs for float types");
541     static_assert(static_cast<VType>(-1) == -1, "type must be signed");
542     static_assert(sizeof(c_[0]) <= sizeof(int), "Abs truncates to int");
543     return Vector4(abs(c_[0]), abs(c_[1]), abs(c_[2]), abs(c_[3]));
544   }
545 
546  private:
547   VType c_[SIZE];
548 };
549 
550 typedef Vector2<uint8>  Vector2_b;
551 typedef Vector2<int16>  Vector2_s;
552 typedef Vector2<int>    Vector2_i;
553 typedef Vector2<float>  Vector2_f;
554 typedef Vector2<double> Vector2_d;
555 
556 typedef Vector3<uint8>  Vector3_b;
557 typedef Vector3<int16>  Vector3_s;
558 typedef Vector3<int>    Vector3_i;
559 typedef Vector3<float>  Vector3_f;
560 typedef Vector3<double> Vector3_d;
561 
562 typedef Vector4<uint8>  Vector4_b;
563 typedef Vector4<int16>  Vector4_s;
564 typedef Vector4<int>    Vector4_i;
565 typedef Vector4<float>  Vector4_f;
566 typedef Vector4<double> Vector4_d;
567 
568 
569 #endif  // S2_UTIL_MATH_VECTOR_H_
570