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