1 // Copyright 2009-2021 Intel Corporation 2 // SPDX-License-Identifier: Apache-2.0 3 4 #pragma once 5 6 #include "../common.h" 7 #include "constants.h" 8 #include "rkmath.h" 9 10 #include "../traits/rktraits.h" 11 12 namespace rkcommon { 13 14 // NOTE: only for identifying vec_t types at compile-time 15 struct vec_base 16 { 17 }; 18 19 // ------------------------------------------------------- 20 // type traits relevant to vec_t<> type compile-time logic 21 // ------------------------------------------------------- 22 23 namespace traits { 24 25 template <typename T> 26 using is_arithmetic_t = enable_if_t<std::is_arithmetic<T>::value>; 27 28 template <typename T> 29 struct is_vec 30 { 31 const static bool value = std::is_base_of<vec_base, T>::value; 32 }; 33 34 template <typename VEC_ELEMENT_T, typename TYPE_IN_QUESTION> 35 struct is_valid_vec_constructor_type 36 { 37 const static bool value = 38 std::is_constructible<VEC_ELEMENT_T, TYPE_IN_QUESTION>::value && 39 !std::is_same<TYPE_IN_QUESTION, VEC_ELEMENT_T>::value && 40 !is_vec<TYPE_IN_QUESTION>::value; 41 }; 42 43 template <typename VEC_ELEMENT_T, typename TYPE_IN_QUESTION> 44 using is_valid_vec_constructor_type_t = enable_if_t< 45 is_valid_vec_constructor_type<VEC_ELEMENT_T, TYPE_IN_QUESTION>::value>; 46 47 } // namespace traits 48 49 namespace math { 50 51 // vec_t<> types ////////////////////////////////////////////////////////// 52 53 template <typename T, int N, bool ALIGN = false> 54 struct vec_t : public vec_base 55 { 56 using scalar_t = T; 57 using Scalar = T; 58 }; 59 60 template <typename T> 61 struct vec_t<T, 2> : public vec_base 62 { 63 using scalar_t = T; 64 using Scalar = T; 65 66 vec_t() = default; 67 68 vec_t(const scalar_t *v) : x(v[0]), y(v[1]) {} 69 70 vec_t(scalar_t s) : x(s), y(s) {} 71 72 template <typename OT, 73 typename = traits::is_valid_vec_constructor_type_t<T, OT>> 74 vec_t(const OT &s) : x(s), y(s) 75 { 76 } 77 78 vec_t(scalar_t x, scalar_t y) : x(x), y(y) {} 79 80 template <typename OT, bool OA> 81 vec_t(const vec_t<OT, 2, OA> &o) : x(o.x), y(o.y) 82 { 83 } 84 85 const T &operator[](const size_t idx) const 86 { 87 assert(idx < 2); 88 return (&x)[idx]; 89 } 90 91 T &operator[](const size_t idx) 92 { 93 assert(idx < 2); 94 return (&x)[idx]; 95 } 96 97 operator T *() 98 { 99 return &x; 100 } 101 102 operator const T *() const 103 { 104 return &x; 105 } 106 107 /*! return result of reduce_add() across all components */ 108 scalar_t sum() const 109 { 110 return x + y; 111 } 112 /*! return result of reduce_mul() across all components */ 113 scalar_t product() const 114 { 115 return x * y; 116 } 117 118 size_t long_product() const 119 { 120 return size_t(x) * size_t(y); 121 } 122 123 // conversion constructor to other types to enable static_cast 124 template <typename OT> 125 explicit operator vec_t<OT, 2>() const 126 { 127 return vec_t<OT, 2>(*this); 128 } 129 130 T x, y; 131 }; 132 133 template <typename T> 134 struct vec_t<T, 3> : public vec_base 135 { 136 using scalar_t = T; 137 using Scalar = T; 138 139 vec_t() = default; 140 141 vec_t(const scalar_t *v) : x(v[0]), y(v[1]), z(v[2]) {} 142 143 vec_t(scalar_t s) : x(s), y(s), z(s) {} 144 145 template <typename OT, 146 typename = traits::is_valid_vec_constructor_type_t<T, OT>> 147 vec_t(const OT &s) : x(s), y(s), z(s) 148 { 149 } 150 151 vec_t(scalar_t x, scalar_t y, scalar_t z) : x(x), y(y), z(z) {} 152 153 template <typename OT, bool OA> 154 vec_t(const vec_t<OT, 2, OA> &o, scalar_t z) : x(o.x), y(o.y), z(z) 155 { 156 } 157 158 template <typename OT, bool OA> 159 vec_t(const vec_t<OT, 3, OA> &o) : x(o.x), y(o.y), z(o.z) 160 { 161 } 162 163 const T &operator[](const size_t axis) const 164 { 165 assert(axis < 3); 166 return (&x)[axis]; 167 } 168 169 T &operator[](const size_t axis) 170 { 171 assert(axis < 3); 172 return (&x)[axis]; 173 } 174 175 operator T *() 176 { 177 return &x; 178 } 179 180 operator const T *() const 181 { 182 return &x; 183 } 184 185 /*! return result of reduce_add() across all components */ 186 scalar_t sum() const 187 { 188 return x + y + z; 189 } 190 191 /*! return result of reduce_mul() across all components */ 192 scalar_t product() const 193 { 194 return x * y * z; 195 } 196 197 size_t long_product() const 198 { 199 return size_t(x) * size_t(y) * size_t(z); 200 } 201 202 // conversion constructor to other types to enable static_cast 203 template <typename OT> 204 explicit operator vec_t<OT, 3>() const 205 { 206 return vec_t<OT, 3>(*this); 207 } 208 209 T x, y, z; 210 }; 211 212 template <typename T> 213 struct vec_t<T, 3, true> : public vec_base 214 { 215 using scalar_t = T; 216 using Scalar = T; 217 218 vec_t() = default; 219 220 vec_t(const scalar_t *v) : x(v[0]), y(v[1]), z(v[2]) {} 221 222 vec_t(scalar_t s) : x(s), y(s), z(s) {} 223 224 template <typename OT, 225 typename = traits::is_valid_vec_constructor_type_t<T, OT>> 226 vec_t(const OT &s) : x(s), y(s), z(s) 227 { 228 } 229 230 vec_t(scalar_t x, scalar_t y, scalar_t z) : x(x), y(y), z(z) {} 231 232 template <typename OT, bool OA> 233 vec_t(const vec_t<OT, 2, OA> &o, scalar_t z) : x(o.x), y(o.y), z(z) 234 { 235 } 236 237 template <typename OT, bool OA> 238 vec_t(const vec_t<OT, 3, OA> &o) : x(o.x), y(o.y), z(o.z) 239 { 240 } 241 242 const T &operator[](const size_t axis) const 243 { 244 assert(axis < 3); 245 return (&x)[axis]; 246 } 247 T &operator[](const size_t axis) 248 { 249 assert(axis < 3); 250 return (&x)[axis]; 251 } 252 253 operator T *() 254 { 255 return &x; 256 } 257 258 operator const T *() const 259 { 260 return &x; 261 } 262 263 /*! return result of reduce_add() across all components */ 264 scalar_t sum() const 265 { 266 return x + y + z; 267 } 268 /*! return result of reduce_mul() across all components */ 269 scalar_t product() const 270 { 271 return x * y * z; 272 } 273 274 size_t long_product() const 275 { 276 return size_t(x) * size_t(y) * size_t(z); 277 } 278 279 operator vec_t<T, 3>() const 280 { 281 return vec_t<T, 3>(x, y, z); 282 } 283 284 // conversion constructor to other types to enable static_cast 285 template <typename OT> 286 explicit operator vec_t<OT, 3, true>() const 287 { 288 return vec_t<OT, 3, true>(*this); 289 } 290 291 T x, y, z; 292 T padding_; 293 }; 294 295 template <typename T> 296 struct vec_t<T, 4> : public vec_base 297 { 298 using scalar_t = T; 299 using Scalar = T; 300 301 vec_t() = default; 302 303 vec_t(const scalar_t *v) : x(v[0]), y(v[1]), z(v[2]), w(v[3]) {} 304 305 vec_t(scalar_t s) : x(s), y(s), z(s), w(s) {} 306 307 template <typename OT, 308 typename = traits::is_valid_vec_constructor_type_t<T, OT>> 309 vec_t(const OT &s) : x(s), y(s), z(s), w(s) 310 { 311 } 312 313 vec_t(scalar_t x, scalar_t y, scalar_t z, scalar_t w) 314 : x(x), y(y), z(z), w(w) 315 { 316 } 317 318 template <typename OT, bool OA> 319 vec_t(const vec_t<OT, 2, OA> &o1, const vec_t<OT, 2, OA> &o2) 320 : x(o1.x), y(o1.y), z(o2.x), w(o2.y) 321 { 322 } 323 324 template <typename OT, bool OA> 325 vec_t(const vec_t<OT, 3, OA> &o, scalar_t w) 326 : x(o.x), y(o.y), z(o.z), w(w) 327 { 328 } 329 330 template <typename OT, bool OA> 331 vec_t(const vec_t<OT, 4, OA> &o) : x(o.x), y(o.y), z(o.z), w(o.w) 332 { 333 } 334 335 const T &operator[](const size_t idx) const 336 { 337 assert(idx < 4); 338 return (&x)[idx]; 339 } 340 T &operator[](const size_t idx) 341 { 342 assert(idx < 4); 343 return (&x)[idx]; 344 } 345 346 operator T *() 347 { 348 return &x; 349 } 350 351 operator const T *() const 352 { 353 return &x; 354 } 355 356 /*! return result of reduce_add() across all components */ 357 scalar_t sum() const 358 { 359 return x + y + z + w; 360 } 361 /*! return result of reduce_mul() across all components */ 362 scalar_t product() const 363 { 364 return x * y * z * w; 365 } 366 367 size_t long_product() const 368 { 369 return size_t(x) * size_t(y) * size_t(z) * size_t(w); 370 } 371 372 // conversion constructor to other types to enable static_cast 373 template <typename OT> 374 explicit operator vec_t<OT, 4>() const 375 { 376 return vec_t<OT, 4>(*this); 377 } 378 379 T x, y, z, w; 380 }; 381 382 // ------------------------------------------------------- 383 // unary operators 384 // ------------------------------------------------------- 385 template <typename T> 386 inline vec_t<T, 2> operator-(const vec_t<T, 2> &v) 387 { 388 return vec_t<T, 2>(-v.x, -v.y); 389 } 390 template <typename T> 391 inline vec_t<T, 3> operator-(const vec_t<T, 3> &v) 392 { 393 return vec_t<T, 3>(-v.x, -v.y, -v.z); 394 } 395 template <typename T> 396 inline vec_t<T, 3, 1> operator-(const vec_t<T, 3, 1> &v) 397 { 398 return vec_t<T, 3, 1>(-v.x, -v.y, -v.z); 399 } 400 template <typename T> 401 inline vec_t<T, 4> operator-(const vec_t<T, 4> &v) 402 { 403 return vec_t<T, 4>(-v.x, -v.y, -v.z, -v.w); 404 } 405 406 template <typename T> 407 inline vec_t<T, 2> operator+(const vec_t<T, 2> &v) 408 { 409 return vec_t<T, 2>(+v.x, +v.y); 410 } 411 template <typename T> 412 inline vec_t<T, 3> operator+(const vec_t<T, 3> &v) 413 { 414 return vec_t<T, 3>(+v.x, +v.y, +v.z); 415 } 416 template <typename T> 417 inline vec_t<T, 3, 1> operator+(const vec_t<T, 3, 1> &v) 418 { 419 return vec_t<T, 3, 1>(+v.x, +v.y, +v.z); 420 } 421 template <typename T> 422 inline vec_t<T, 4> operator+(const vec_t<T, 4> &v) 423 { 424 return vec_t<T, 4>(+v.x, +v.y, +v.z, +v.w); 425 } 426 427 using std::abs; 428 429 // ------------------------------------------------------- 430 // unary functors 431 // ------------------------------------------------------- 432 #define unary_functor(op) \ 433 template <typename T> \ 434 inline vec_t<T, 2> op(const vec_t<T, 2> &v) \ 435 { \ 436 return vec_t<T, 2>(op(v.x), op(v.y)); \ 437 } \ 438 template <typename T> \ 439 inline vec_t<T, 3> op(const vec_t<T, 3> &v) \ 440 { \ 441 return vec_t<T, 3>(op(v.x), op(v.y), op(v.z)); \ 442 } \ 443 template <typename T> \ 444 inline vec_t<T, 3, true> op(const vec_t<T, 3, 1> &v) \ 445 { \ 446 return vec_t<T, 3, 1>(op(v.x), op(v.y), op(v.z)); \ 447 } \ 448 template <typename T> \ 449 inline vec_t<T, 4> op(const vec_t<T, 4> &v) \ 450 { \ 451 return vec_t<T, 4>(op(v.x), op(v.y), op(v.z), op(v.w)); \ 452 } 453 454 // clang-format off 455 unary_functor(rcp) 456 unary_functor(rcp_safe) 457 unary_functor(abs) 458 unary_functor(sin) 459 unary_functor(cos) 460 // clang-format on 461 #undef unary_functor 462 463 // ------------------------------------------------------- 464 // binary arithmetic operators 465 // ------------------------------------------------------- 466 467 #define binary_operator(name, op) \ 468 /* "vec op vec" */ \ 469 template <typename T> \ 470 inline vec_t<T, 2> name(const vec_t<T, 2> &a, const vec_t<T, 2> &b) \ 471 { \ 472 return vec_t<T, 2>(a.x op b.x, a.y op b.y); \ 473 } \ 474 \ 475 template <typename T, bool A, bool B> \ 476 inline vec_t<T, 3> name(const vec_t<T, 3, A> &a, const vec_t<T, 3, B> &b) \ 477 { \ 478 return vec_t<T, 3>(a.x op b.x, a.y op b.y, a.z op b.z); \ 479 } \ 480 \ 481 template <typename T> \ 482 inline vec_t<T, 4> name(const vec_t<T, 4> &a, const vec_t<T, 4> &b) \ 483 { \ 484 return vec_t<T, 4>(a.x op b.x, a.y op b.y, a.z op b.z, a.w op b.w); \ 485 } \ 486 \ 487 /* "vec<T, N> op vec<U, N>" (element types don't match) */ \ 488 template <typename T, \ 489 typename U, \ 490 int N, \ 491 bool A, \ 492 typename = traits::is_not_same_t<T, U>> \ 493 inline auto name(const vec_t<T, N, A> &a, const vec_t<U, N, A> &b) \ 494 ->vec_t<decltype(T() op U()), N, A> \ 495 { \ 496 using vector_t = vec_t<decltype(T() op U()), N, A>; \ 497 return vector_t(vector_t(a) op vector_t(b)); \ 498 } \ 499 \ 500 /* "vec op scalar" */ \ 501 template <typename T> \ 502 inline vec_t<T, 2> name(const vec_t<T, 2> &a, const T &b) \ 503 { \ 504 return vec_t<T, 2>(a.x op b, a.y op b); \ 505 } \ 506 \ 507 template <typename T, bool A> \ 508 inline vec_t<T, 3> name(const vec_t<T, 3, A> &a, const T &b) \ 509 { \ 510 return vec_t<T, 3>(a.x op b, a.y op b, a.z op b); \ 511 } \ 512 \ 513 template <typename T> \ 514 inline vec_t<T, 4> name(const vec_t<T, 4> &a, const T &b) \ 515 { \ 516 return vec_t<T, 4>(a.x op b, a.y op b, a.z op b, a.w op b); \ 517 } \ 518 \ 519 /* "vec<T, N> op U" (element types don't match) */ \ 520 template <typename T, \ 521 typename U, \ 522 int N, \ 523 bool A, \ 524 typename = traits::is_not_same_t<T, U>> \ 525 inline auto name(const vec_t<T, N, A> &a, const U &b) \ 526 ->vec_t<decltype(T() op U()), N, A> \ 527 { \ 528 using scalar_t = decltype(T() op U()); \ 529 using vector_t = vec_t<scalar_t, N, A>; \ 530 return vector_t(vector_t(a) op scalar_t(b)); \ 531 } \ 532 \ 533 /* "scalar op vec" */ \ 534 template <typename T> \ 535 inline vec_t<T, 2> name(const T &a, const vec_t<T, 2> &b) \ 536 { \ 537 return vec_t<T, 2>(a op b.x, a op b.y); \ 538 } \ 539 \ 540 template <typename T, bool A> \ 541 inline vec_t<T, 3> name(const T &a, const vec_t<T, 3, A> &b) \ 542 { \ 543 return vec_t<T, 3>(a op b.x, a op b.y, a op b.z); \ 544 } \ 545 \ 546 template <typename T> \ 547 inline vec_t<T, 4> name(const T &a, const vec_t<T, 4> &b) \ 548 { \ 549 return vec_t<T, 4>(a op b.x, a op b.y, a op b.z, a op b.w); \ 550 } \ 551 \ 552 /* "T op vec<U, N>" (element types don't match) */ \ 553 template <typename T, \ 554 typename U, \ 555 int N, \ 556 bool A, \ 557 typename = traits::is_not_same_t<T, U>> \ 558 inline auto name(const T &a, const vec_t<U, N, A> &b) \ 559 ->vec_t<decltype(T() op U()), N, A> \ 560 { \ 561 using scalar_t = decltype(T() op U()); \ 562 using vector_t = vec_t<scalar_t, N, A>; \ 563 return vector_t(scalar_t(a) op vector_t(b)); \ 564 } 565 566 // clang-format off 567 binary_operator(operator+, +) 568 binary_operator(operator-, -) 569 binary_operator(operator*, *) 570 binary_operator(operator/, /) 571 binary_operator(operator%, %) 572 // clang-format on 573 #undef binary_operator 574 575 // ------------------------------------------------------- 576 // binary arithmetic assignment operators 577 // ------------------------------------------------------- 578 #define binary_operator(name, op) \ 579 /* "vec op vec" */ \ 580 template <typename T, typename U> \ 581 inline vec_t<T, 2> &name(vec_t<T, 2> &a, const vec_t<U, 2> &b) \ 582 { \ 583 a.x op b.x; \ 584 a.y op b.y; \ 585 return a; \ 586 } \ 587 \ 588 template <typename T, typename U, bool A, bool B> \ 589 inline vec_t<T, 3, A> &name(vec_t<T, 3, A> &a, const vec_t<U, 3, B> &b) \ 590 { \ 591 a.x op b.x; \ 592 a.y op b.y; \ 593 a.z op b.z; \ 594 return a; \ 595 } \ 596 \ 597 template <typename T, typename U> \ 598 inline vec_t<T, 4> &name(vec_t<T, 4> &a, const vec_t<U, 4> &b) \ 599 { \ 600 a.x op b.x; \ 601 a.y op b.y; \ 602 a.z op b.z; \ 603 a.w op b.w; \ 604 return a; \ 605 } \ 606 \ 607 /* "vec op scalar" */ \ 608 template <typename T, typename U, typename = traits::is_arithmetic_t<U>> \ 609 inline vec_t<T, 2> &name(vec_t<T, 2> &a, const U &b) \ 610 { \ 611 a.x op b; \ 612 a.y op b; \ 613 return a; \ 614 } \ 615 \ 616 template <typename T, \ 617 typename U, \ 618 bool A, \ 619 typename = traits::is_arithmetic_t<U>> \ 620 inline vec_t<T, 3, A> &name(vec_t<T, 3, A> &a, const U &b) \ 621 { \ 622 a.x op b; \ 623 a.y op b; \ 624 a.z op b; \ 625 return a; \ 626 } \ 627 \ 628 template <typename T, typename U, typename = traits::is_arithmetic_t<U>> \ 629 inline vec_t<T, 4> &name(vec_t<T, 4> &a, const U &b) \ 630 { \ 631 a.x op b; \ 632 a.y op b; \ 633 a.z op b; \ 634 a.w op b; \ 635 return a; \ 636 } 637 638 // clang-format off 639 binary_operator(operator+=, +=) 640 binary_operator(operator-=, -=) 641 binary_operator(operator*=, *=) 642 binary_operator(operator/=, /=) 643 binary_operator(operator%=, %=) 644 // clang-format on 645 #undef binary_operator 646 647 // ------------------------------------------------------- 648 // ternary operators (just for compatibility with old embree 649 // ------------------------------------------------------- 650 template <typename T, bool A> 651 inline vec_t<T, 3, A> madd(const vec_t<T, 3, A> &a, 652 const vec_t<T, 3, A> &b, 653 const vec_t<T, 3, A> &c) 654 { 655 return vec_t<T, 3, A>( 656 madd(a.x, b.x, c.x), madd(a.y, b.y, c.y), madd(a.z, b.z, c.z)); 657 } 658 659 // ------------------------------------------------------- 660 // comparison operators 661 // ------------------------------------------------------- 662 template <typename T> 663 inline bool operator==(const vec_t<T, 2> &a, const vec_t<T, 2> &b) 664 { 665 return a.x == b.x && a.y == b.y; 666 } 667 668 template <typename T, bool A, bool B> 669 inline bool operator==(const vec_t<T, 3, A> &a, const vec_t<T, 3, B> &b) 670 { 671 return a.x == b.x && a.y == b.y && a.z == b.z; 672 } 673 674 template <typename T> 675 inline bool operator==(const vec_t<T, 4> &a, const vec_t<T, 4> &b) 676 { 677 return a.x == b.x && a.y == b.y && a.z == b.z && a.w == b.w; 678 } 679 680 template <typename T> 681 inline bool operator!=(const vec_t<T, 2> &a, const vec_t<T, 2> &b) 682 { 683 return !(a == b); 684 } 685 686 template <typename T, bool A, bool B> 687 inline bool operator!=(const vec_t<T, 3, A> &a, const vec_t<T, 3, B> &b) 688 { 689 return !(a == b); 690 } 691 692 template <typename T> 693 inline bool operator!=(const vec_t<T, 4> &a, const vec_t<T, 4> &b) 694 { 695 return !(a == b); 696 } 697 698 // 'anyLessThan' - return true if any component is less than the other vec's 699 template <typename T> 700 inline bool anyLessThan(const vec_t<T, 2> &a, const vec_t<T, 2> &b) 701 { 702 return a.x < b.x || a.y < b.y; 703 } 704 705 template <typename T, bool A, bool B> 706 inline bool anyLessThan(const vec_t<T, 3, A> &a, const vec_t<T, 3, B> &b) 707 { 708 return a.x < b.x || a.y < b.y || a.z < b.z; 709 } 710 711 template <typename T> 712 inline bool anyLessThan(const vec_t<T, 4> &a, const vec_t<T, 4> &b) 713 { 714 return a.x < b.x || a.y < b.y || a.z < b.z || a.w < b.w; 715 } 716 717 // ------------------------------------------------------- 718 // dot functions 719 // ------------------------------------------------------- 720 template <typename T> 721 inline T dot(const vec_t<T, 2> &a, const vec_t<T, 2> &b) 722 { 723 return a.x * b.x + a.y * b.y; 724 } 725 template <typename T> 726 inline T dot(const vec_t<T, 3> &a, const vec_t<T, 3> &b) 727 { 728 return a.x * b.x + a.y * b.y + a.z * b.z; 729 } 730 template <typename T> 731 inline T dot(const vec_t<T, 3, 1> &a, const vec_t<T, 3, 1> &b) 732 { 733 return a.x * b.x + a.y * b.y + a.z * b.z; 734 } 735 template <typename T> 736 inline T dot(const vec_t<T, 3> &a, const vec_t<T, 3, 1> &b) 737 { 738 return a.x * b.x + a.y * b.y + a.z * b.z; 739 } 740 template <typename T> 741 inline T dot(const vec_t<T, 3, 1> &a, const vec_t<T, 3> &b) 742 { 743 return a.x * b.x + a.y * b.y + a.z * b.z; 744 } 745 template <typename T> 746 inline T dot(const vec_t<T, 4> &a, const vec_t<T, 4> &b) 747 { 748 return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w; 749 } 750 751 // ------------------------------------------------------- 752 // length functions 753 // ------------------------------------------------------- 754 template <typename T, int N, bool A> 755 inline T length(const vec_t<T, N, A> &v) 756 { 757 return sqrt(dot(v, v)); 758 } 759 760 // ------------------------------------------------------- 761 // cross product 762 // ------------------------------------------------------- 763 template <typename T, bool A, bool B> 764 inline vec_t<T, 3> cross(const vec_t<T, 3, A> &a, const vec_t<T, 3, B> &b) 765 { 766 return vec_t<T, 3>( 767 a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x); 768 } 769 770 // ------------------------------------------------------- 771 // normalize() 772 // ------------------------------------------------------- 773 template <typename T, int N, bool A> 774 inline vec_t<T, N, A> normalize(const vec_t<T, N, A> &v) 775 { 776 return v * rsqrt(dot(v, v)); 777 } 778 779 template <typename T, int N, bool A> 780 inline vec_t<T, N, A> safe_normalize(const vec_t<T, N, A> &v) 781 { 782 return v * rsqrt(max(T(1e-6), dot(v, v))); 783 } 784 785 // ------------------------------------------------------- 786 // interpolation 787 // ------------------------------------------------------- 788 789 // barycentric interpolation 790 template <typename T, int N, bool A> 791 inline vec_t<T, N, A> interpolate_uv(const vec_t<T, 3> &f, 792 const vec_t<T, N, A> &a, 793 const vec_t<T, N, A> &b, 794 const vec_t<T, N, A> &c) 795 { 796 return f.x * a + f.y * b + f.z * c; 797 } 798 799 // ------------------------------------------------------- 800 // ostream operators 801 // ------------------------------------------------------- 802 template <typename T> 803 inline std::ostream &operator<<(std::ostream &o, const vec_t<T, 2> &v) 804 { 805 o << "(" << v.x << "," << v.y << ")"; 806 return o; 807 } 808 template <typename T, bool A> 809 inline std::ostream &operator<<(std::ostream &o, const vec_t<T, 3, A> &v) 810 { 811 o << "(" << v.x << "," << v.y << "," << v.z << ")"; 812 return o; 813 } 814 template <typename T> 815 inline std::ostream &operator<<(std::ostream &o, const vec_t<T, 4> &v) 816 { 817 o << "(" << v.x << "," << v.y << "," << v.z << "," << v.w << ")"; 818 return o; 819 } 820 821 // "inherit" std::min/max/etc for basic types 822 using std::max; 823 using std::min; 824 825 // ------------------------------------------------------- 826 // binary functors 827 // ------------------------------------------------------- 828 #define define_functor(f) \ 829 template <typename T> \ 830 inline vec_t<T, 2> f(const vec_t<T, 2> &a, const vec_t<T, 2> &b) \ 831 { \ 832 return vec_t<T, 2>(f(a.x, b.x), f(a.y, b.y)); \ 833 } \ 834 \ 835 template <typename T, bool A> \ 836 inline vec_t<T, 3, A> f(const vec_t<T, 3, A> &a, const vec_t<T, 3, A> &b) \ 837 { \ 838 return vec_t<T, 3, A>(f(a.x, b.x), f(a.y, b.y), f(a.z, b.z)); \ 839 } \ 840 \ 841 template <typename T> \ 842 inline vec_t<T, 4> f(const vec_t<T, 4> &a, const vec_t<T, 4> &b) \ 843 { \ 844 return vec_t<T, 4>(f(a.x, b.x), f(a.y, b.y), f(a.z, b.z), f(a.w, b.w)); \ 845 } 846 847 // clang-format off 848 define_functor(min) 849 define_functor(max) 850 define_functor(divRoundUp) 851 // clang-format on 852 #undef define_functor 853 854 // ------------------------------------------------------- 855 // reductions 856 // ------------------------------------------------------- 857 template <typename T, bool A> 858 inline T reduce_add(const vec_t<T, 2, A> &v) 859 { 860 return v.x + v.y; 861 } 862 template <typename T, bool A> 863 inline T reduce_add(const vec_t<T, 3, A> &v) 864 { 865 return v.x + v.y + v.z; 866 } 867 template <typename T, bool A> 868 inline T reduce_add(const vec_t<T, 4, A> &v) 869 { 870 return v.x + v.y + v.z + v.w; 871 } 872 873 template <typename T, bool A> 874 inline T reduce_mul(const vec_t<T, 2, A> &v) 875 { 876 return v.x * v.y; 877 } 878 template <typename T, bool A> 879 inline T reduce_mul(const vec_t<T, 3, A> &v) 880 { 881 return v.x * v.y * v.z; 882 } 883 template <typename T, bool A> 884 inline T reduce_mul(const vec_t<T, 4, A> &v) 885 { 886 return v.x * v.y * v.z * v.w; 887 } 888 889 template <typename T, bool A> 890 inline T reduce_min(const vec_t<T, 2, A> &v) 891 { 892 return min(v.x, v.y); 893 } 894 template <typename T, bool A> 895 inline T reduce_min(const vec_t<T, 3, A> &v) 896 { 897 return min(min(v.x, v.y), v.z); 898 } 899 template <typename T, bool A> 900 inline T reduce_min(const vec_t<T, 4, A> &v) 901 { 902 return min(min(v.x, v.y), min(v.z, v.w)); 903 } 904 905 template <typename T, bool A> 906 inline T reduce_max(const vec_t<T, 2, A> &v) 907 { 908 return max(v.x, v.y); 909 } 910 template <typename T, bool A> 911 inline T reduce_max(const vec_t<T, 3, A> &v) 912 { 913 return max(max(v.x, v.y), v.z); 914 } 915 template <typename T, bool A> 916 inline T reduce_max(const vec_t<T, 4, A> &v) 917 { 918 return max(max(v.x, v.y), max(v.z, v.w)); 919 } 920 921 // ------------------------------------------------------- 922 // all vec2 variants 923 // ------------------------------------------------------- 924 typedef vec_t<uint8_t, 2> vec2uc; 925 typedef vec_t<int8_t, 2> vec2c; 926 typedef vec_t<uint16_t, 2> vec2us; 927 typedef vec_t<int16_t, 2> vec2s; 928 typedef vec_t<uint32_t, 2> vec2ui; 929 typedef vec_t<int32_t, 2> vec2i; 930 typedef vec_t<uint64_t, 2> vec2ul; 931 typedef vec_t<int64_t, 2> vec2l; 932 typedef vec_t<float, 2> vec2f; 933 typedef vec_t<double, 2> vec2d; 934 935 // ------------------------------------------------------- 936 // all vec3 variants 937 // ------------------------------------------------------- 938 typedef vec_t<uint8_t, 3> vec3uc; 939 typedef vec_t<int8_t, 3> vec3c; 940 typedef vec_t<uint16_t, 3> vec3us; 941 typedef vec_t<int16_t, 3> vec3s; 942 typedef vec_t<uint32_t, 3> vec3ui; 943 typedef vec_t<int32_t, 3> vec3i; 944 typedef vec_t<uint64_t, 3> vec3ul; 945 typedef vec_t<int64_t, 3> vec3l; 946 typedef vec_t<float, 3> vec3f; 947 typedef vec_t<double, 3> vec3d; 948 949 typedef vec_t<float, 3, 1> vec3fa; 950 typedef vec_t<int, 3, 1> vec3ia; 951 952 // ------------------------------------------------------- 953 // all vec4 variants 954 // ------------------------------------------------------- 955 typedef vec_t<uint8_t, 4> vec4uc; 956 typedef vec_t<int8_t, 4> vec4c; 957 typedef vec_t<uint16_t, 4> vec4us; 958 typedef vec_t<int16_t, 4> vec4s; 959 typedef vec_t<uint32_t, 4> vec4ui; 960 typedef vec_t<int32_t, 4> vec4i; 961 typedef vec_t<uint64_t, 4> vec4ul; 962 typedef vec_t<int64_t, 4> vec4l; 963 typedef vec_t<float, 4> vec4f; 964 typedef vec_t<double, 4> vec4d; 965 966 template <typename T, int N> 967 inline size_t arg_max(const vec_t<T, N> &v) 968 { 969 size_t maxIdx = 0; 970 for (size_t i = 1; i < N; i++) 971 if (v[i] > v[maxIdx]) 972 maxIdx = i; 973 return maxIdx; 974 } 975 976 } // namespace math 977 } // namespace rkcommon 978 979 /*! template specialization for std::less comparison operator; 980 * we need those to be able to put vec's in std::map etc @{ */ 981 /* Defining just operator< is prone to bugs, because a definition of an 982 * ordering of vectors is a bit arbitrary and depends on the context. 983 * For example, in box::extend we certainly want the element-wise min/max and 984 * not the std::min/std::max made applicable by vec3f::operator<. 985 */ 986 namespace std { 987 template <typename T> 988 struct less<rkcommon::math::vec_t<T, 2>> 989 { 990 inline bool operator()(const rkcommon::math::vec_t<T, 2> &a, 991 const rkcommon::math::vec_t<T, 2> &b) const 992 { 993 return (a.x < b.x) || ((a.x == b.x) && (a.y < b.y)); 994 } 995 }; 996 997 template <typename T, bool A> 998 struct less<rkcommon::math::vec_t<T, 3, A>> 999 { 1000 inline bool operator()(const rkcommon::math::vec_t<T, 3, A> &a, 1001 const rkcommon::math::vec_t<T, 3, A> &b) const 1002 { 1003 return (a.x < b.x) || 1004 ((a.x == b.x) && ((a.y < b.y) || ((a.y == b.y) && (a.z < b.z)))); 1005 } 1006 }; 1007 1008 template <typename T> 1009 struct less<rkcommon::math::vec_t<T, 4>> 1010 { 1011 inline bool operator()(const rkcommon::math::vec_t<T, 4> &a, 1012 const rkcommon::math::vec_t<T, 4> &b) const 1013 { 1014 return (a.x < b.x) || 1015 ((a.x == b.x) && 1016 ((a.y < b.y) || 1017 ((a.y == b.y) && 1018 ((a.z < b.z) || ((a.z == b.z) && (a.w < b.w)))))); 1019 } 1020 }; 1021 1022 } // namespace std 1023