TVecHelpers.h revision 11ecb63414d2fea2f4217db8bb06a998bcf8b425
1/* 2 * Copyright 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 18#ifndef UI_TVECHELPERS_H_ 19#define UI_TVECHELPERS_H_ 20 21#include <math.h> 22#include <stdint.h> 23#include <sys/types.h> 24 25#include <cmath> 26#include <limits> 27#include <iostream> 28 29#define PURE __attribute__((pure)) 30 31#if __cplusplus >= 201402L 32#define CONSTEXPR constexpr 33#else 34#define CONSTEXPR 35#endif 36 37namespace android { 38namespace details { 39// ------------------------------------------------------------------------------------- 40 41/* 42 * No user serviceable parts here. 43 * 44 * Don't use this file directly, instead include ui/vec{2|3|4}.h 45 */ 46 47/* 48 * TVec{Add|Product}Operators implements basic arithmetic and basic compound assignments 49 * operators on a vector of type BASE<T>. 50 * 51 * BASE only needs to implement operator[] and size(). 52 * By simply inheriting from TVec{Add|Product}Operators<BASE, T> BASE will automatically 53 * get all the functionality here. 54 */ 55 56template <template<typename T> class VECTOR, typename T> 57class TVecAddOperators { 58public: 59 /* compound assignment from a another vector of the same size but different 60 * element type. 61 */ 62 template<typename OTHER> 63 VECTOR<T>& operator +=(const VECTOR<OTHER>& v) { 64 VECTOR<T>& lhs = static_cast<VECTOR<T>&>(*this); 65 for (size_t i = 0; i < lhs.size(); i++) { 66 lhs[i] += v[i]; 67 } 68 return lhs; 69 } 70 template<typename OTHER> 71 VECTOR<T>& operator -=(const VECTOR<OTHER>& v) { 72 VECTOR<T>& lhs = static_cast<VECTOR<T>&>(*this); 73 for (size_t i = 0; i < lhs.size(); i++) { 74 lhs[i] -= v[i]; 75 } 76 return lhs; 77 } 78 79 /* compound assignment from a another vector of the same type. 80 * These operators can be used for implicit conversion and handle operations 81 * like "vector *= scalar" by letting the compiler implicitly convert a scalar 82 * to a vector (assuming the BASE<T> allows it). 83 */ 84 VECTOR<T>& operator +=(const VECTOR<T>& v) { 85 VECTOR<T>& lhs = static_cast<VECTOR<T>&>(*this); 86 for (size_t i = 0; i < lhs.size(); i++) { 87 lhs[i] += v[i]; 88 } 89 return lhs; 90 } 91 VECTOR<T>& operator -=(const VECTOR<T>& v) { 92 VECTOR<T>& lhs = static_cast<VECTOR<T>&>(*this); 93 for (size_t i = 0; i < lhs.size(); i++) { 94 lhs[i] -= v[i]; 95 } 96 return lhs; 97 } 98 99 /* 100 * NOTE: the functions below ARE NOT member methods. They are friend functions 101 * with they definition inlined with their declaration. This makes these 102 * template functions available to the compiler when (and only when) this class 103 * is instantiated, at which point they're only templated on the 2nd parameter 104 * (the first one, BASE<T> being known). 105 */ 106 107 /* The operators below handle operation between vectors of the same size 108 * but of a different element type. 109 */ 110 template<typename RT> 111 friend inline constexpr VECTOR<T> PURE operator +(VECTOR<T> lv, const VECTOR<RT>& rv) { 112 // don't pass lv by reference because we need a copy anyways 113 return lv += rv; 114 } 115 template<typename RT> 116 friend inline constexpr VECTOR<T> PURE operator -(VECTOR<T> lv, const VECTOR<RT>& rv) { 117 // don't pass lv by reference because we need a copy anyways 118 return lv -= rv; 119 } 120 121 /* The operators below (which are not templates once this class is instanced, 122 * i.e.: BASE<T> is known) can be used for implicit conversion on both sides. 123 * These handle operations like "vector + scalar" and "scalar + vector" by 124 * letting the compiler implicitly convert a scalar to a vector (assuming 125 * the BASE<T> allows it). 126 */ 127 friend inline constexpr VECTOR<T> PURE operator +(VECTOR<T> lv, const VECTOR<T>& rv) { 128 // don't pass lv by reference because we need a copy anyways 129 return lv += rv; 130 } 131 friend inline constexpr VECTOR<T> PURE operator -(VECTOR<T> lv, const VECTOR<T>& rv) { 132 // don't pass lv by reference because we need a copy anyways 133 return lv -= rv; 134 } 135}; 136 137template<template<typename T> class VECTOR, typename T> 138class TVecProductOperators { 139public: 140 /* compound assignment from a another vector of the same size but different 141 * element type. 142 */ 143 template<typename OTHER> 144 VECTOR<T>& operator *=(const VECTOR<OTHER>& v) { 145 VECTOR<T>& lhs = static_cast<VECTOR<T>&>(*this); 146 for (size_t i = 0; i < lhs.size(); i++) { 147 lhs[i] *= v[i]; 148 } 149 return lhs; 150 } 151 template<typename OTHER> 152 VECTOR<T>& operator /=(const VECTOR<OTHER>& v) { 153 VECTOR<T>& lhs = static_cast<VECTOR<T>&>(*this); 154 for (size_t i = 0; i < lhs.size(); i++) { 155 lhs[i] /= v[i]; 156 } 157 return lhs; 158 } 159 160 /* compound assignment from a another vector of the same type. 161 * These operators can be used for implicit conversion and handle operations 162 * like "vector *= scalar" by letting the compiler implicitly convert a scalar 163 * to a vector (assuming the BASE<T> allows it). 164 */ 165 VECTOR<T>& operator *=(const VECTOR<T>& v) { 166 VECTOR<T>& lhs = static_cast<VECTOR<T>&>(*this); 167 for (size_t i = 0; i < lhs.size(); i++) { 168 lhs[i] *= v[i]; 169 } 170 return lhs; 171 } 172 VECTOR<T>& operator /=(const VECTOR<T>& v) { 173 VECTOR<T>& lhs = static_cast<VECTOR<T>&>(*this); 174 for (size_t i = 0; i < lhs.size(); i++) { 175 lhs[i] /= v[i]; 176 } 177 return lhs; 178 } 179 180 /* 181 * NOTE: the functions below ARE NOT member methods. They are friend functions 182 * with they definition inlined with their declaration. This makes these 183 * template functions available to the compiler when (and only when) this class 184 * is instantiated, at which point they're only templated on the 2nd parameter 185 * (the first one, BASE<T> being known). 186 */ 187 188 /* The operators below handle operation between vectors of the same size 189 * but of a different element type. 190 */ 191 template<typename RT> 192 friend inline constexpr VECTOR<T> PURE operator *(VECTOR<T> lv, const VECTOR<RT>& rv) { 193 // don't pass lv by reference because we need a copy anyways 194 return lv *= rv; 195 } 196 template<typename RT> 197 friend inline constexpr VECTOR<T> PURE operator /(VECTOR<T> lv, const VECTOR<RT>& rv) { 198 // don't pass lv by reference because we need a copy anyways 199 return lv /= rv; 200 } 201 202 /* The operators below (which are not templates once this class is instanced, 203 * i.e.: BASE<T> is known) can be used for implicit conversion on both sides. 204 * These handle operations like "vector * scalar" and "scalar * vector" by 205 * letting the compiler implicitly convert a scalar to a vector (assuming 206 * the BASE<T> allows it). 207 */ 208 friend inline constexpr VECTOR<T> PURE operator *(VECTOR<T> lv, const VECTOR<T>& rv) { 209 // don't pass lv by reference because we need a copy anyways 210 return lv *= rv; 211 } 212 friend inline constexpr VECTOR<T> PURE operator /(VECTOR<T> lv, const VECTOR<T>& rv) { 213 // don't pass lv by reference because we need a copy anyways 214 return lv /= rv; 215 } 216}; 217 218/* 219 * TVecUnaryOperators implements unary operators on a vector of type BASE<T>. 220 * 221 * BASE only needs to implement operator[] and size(). 222 * By simply inheriting from TVecUnaryOperators<BASE, T> BASE will automatically 223 * get all the functionality here. 224 * 225 * These operators are implemented as friend functions of TVecUnaryOperators<BASE, T> 226 */ 227template<template<typename T> class VECTOR, typename T> 228class TVecUnaryOperators { 229public: 230 VECTOR<T>& operator ++() { 231 VECTOR<T>& rhs = static_cast<VECTOR<T>&>(*this); 232 for (size_t i = 0; i < rhs.size(); i++) { 233 ++rhs[i]; 234 } 235 return rhs; 236 } 237 238 VECTOR<T>& operator --() { 239 VECTOR<T>& rhs = static_cast<VECTOR<T>&>(*this); 240 for (size_t i = 0; i < rhs.size(); i++) { 241 --rhs[i]; 242 } 243 return rhs; 244 } 245 246 CONSTEXPR VECTOR<T> operator -() const { 247 VECTOR<T> r(VECTOR<T>::NO_INIT); 248 VECTOR<T> const& rv(static_cast<VECTOR<T> const&>(*this)); 249 for (size_t i = 0; i < r.size(); i++) { 250 r[i] = -rv[i]; 251 } 252 return r; 253 } 254}; 255 256/* 257 * TVecComparisonOperators implements relational/comparison operators 258 * on a vector of type BASE<T>. 259 * 260 * BASE only needs to implement operator[] and size(). 261 * By simply inheriting from TVecComparisonOperators<BASE, T> BASE will automatically 262 * get all the functionality here. 263 */ 264template<template<typename T> class VECTOR, typename T> 265class TVecComparisonOperators { 266public: 267 /* 268 * NOTE: the functions below ARE NOT member methods. They are friend functions 269 * with they definition inlined with their declaration. This makes these 270 * template functions available to the compiler when (and only when) this class 271 * is instantiated, at which point they're only templated on the 2nd parameter 272 * (the first one, BASE<T> being known). 273 */ 274 template<typename RT> 275 friend inline 276 bool PURE operator ==(const VECTOR<T>& lv, const VECTOR<RT>& rv) { 277 for (size_t i = 0; i < lv.size(); i++) 278 if (lv[i] != rv[i]) 279 return false; 280 return true; 281 } 282 283 template<typename RT> 284 friend inline 285 bool PURE operator !=(const VECTOR<T>& lv, const VECTOR<RT>& rv) { 286 return !operator ==(lv, rv); 287 } 288 289 template<typename RT> 290 friend inline 291 bool PURE operator >(const VECTOR<T>& lv, const VECTOR<RT>& rv) { 292 for (size_t i = 0; i < lv.size(); i++) { 293 if (lv[i] == rv[i]) { 294 continue; 295 } 296 return lv[i] > rv[i]; 297 } 298 return false; 299 } 300 301 template<typename RT> 302 friend inline 303 constexpr bool PURE operator <=(const VECTOR<T>& lv, const VECTOR<RT>& rv) { 304 return !(lv > rv); 305 } 306 307 template<typename RT> 308 friend inline 309 bool PURE operator <(const VECTOR<T>& lv, const VECTOR<RT>& rv) { 310 for (size_t i = 0; i < lv.size(); i++) { 311 if (lv[i] == rv[i]) { 312 continue; 313 } 314 return lv[i] < rv[i]; 315 } 316 return false; 317 } 318 319 template<typename RT> 320 friend inline 321 constexpr bool PURE operator >=(const VECTOR<T>& lv, const VECTOR<RT>& rv) { 322 return !(lv < rv); 323 } 324 325 template<typename RT> 326 friend inline 327 constexpr VECTOR<bool> PURE equal(const VECTOR<T>& lv, const VECTOR<RT>& rv) { 328 VECTOR<bool> r; 329 for (size_t i = 0; i < lv.size(); i++) { 330 r[i] = lv[i] == rv[i]; 331 } 332 return r; 333 } 334 335 template<typename RT> 336 friend inline 337 constexpr VECTOR<bool> PURE notEqual(const VECTOR<T>& lv, const VECTOR<RT>& rv) { 338 VECTOR<bool> r; 339 for (size_t i = 0; i < lv.size(); i++) { 340 r[i] = lv[i] != rv[i]; 341 } 342 return r; 343 } 344 345 template<typename RT> 346 friend inline 347 constexpr VECTOR<bool> PURE lessThan(const VECTOR<T>& lv, const VECTOR<RT>& rv) { 348 VECTOR<bool> r; 349 for (size_t i = 0; i < lv.size(); i++) { 350 r[i] = lv[i] < rv[i]; 351 } 352 return r; 353 } 354 355 template<typename RT> 356 friend inline 357 constexpr VECTOR<bool> PURE lessThanEqual(const VECTOR<T>& lv, const VECTOR<RT>& rv) { 358 VECTOR<bool> r; 359 for (size_t i = 0; i < lv.size(); i++) { 360 r[i] = lv[i] <= rv[i]; 361 } 362 return r; 363 } 364 365 template<typename RT> 366 friend inline 367 constexpr VECTOR<bool> PURE greaterThan(const VECTOR<T>& lv, const VECTOR<RT>& rv) { 368 VECTOR<bool> r; 369 for (size_t i = 0; i < lv.size(); i++) { 370 r[i] = lv[i] > rv[i]; 371 } 372 return r; 373 } 374 375 template<typename RT> 376 friend inline 377 constexpr VECTOR<bool> PURE greaterThanEqual(const VECTOR<T>& lv, const VECTOR<RT>& rv) { 378 VECTOR<bool> r; 379 for (size_t i = 0; i < lv.size(); i++) { 380 r[i] = lv[i] >= rv[i]; 381 } 382 return r; 383 } 384}; 385 386/* 387 * TVecFunctions implements functions on a vector of type BASE<T>. 388 * 389 * BASE only needs to implement operator[] and size(). 390 * By simply inheriting from TVecFunctions<BASE, T> BASE will automatically 391 * get all the functionality here. 392 */ 393template<template<typename T> class VECTOR, typename T> 394class TVecFunctions { 395public: 396 /* 397 * NOTE: the functions below ARE NOT member methods. They are friend functions 398 * with they definition inlined with their declaration. This makes these 399 * template functions available to the compiler when (and only when) this class 400 * is instantiated, at which point they're only templated on the 2nd parameter 401 * (the first one, BASE<T> being known). 402 */ 403 template<typename RT> 404 friend inline CONSTEXPR T PURE dot(const VECTOR<T>& lv, const VECTOR<RT>& rv) { 405 T r(0); 406 for (size_t i = 0; i < lv.size(); i++) { 407 //r = std::fma(lv[i], rv[i], r); 408 r += lv[i] * rv[i]; 409 } 410 return r; 411 } 412 413 friend inline constexpr T PURE norm(const VECTOR<T>& lv) { 414 return std::sqrt(dot(lv, lv)); 415 } 416 417 friend inline constexpr T PURE length(const VECTOR<T>& lv) { 418 return norm(lv); 419 } 420 421 friend inline constexpr T PURE norm2(const VECTOR<T>& lv) { 422 return dot(lv, lv); 423 } 424 425 friend inline constexpr T PURE length2(const VECTOR<T>& lv) { 426 return norm2(lv); 427 } 428 429 template<typename RT> 430 friend inline constexpr T PURE distance(const VECTOR<T>& lv, const VECTOR<RT>& rv) { 431 return length(rv - lv); 432 } 433 434 template<typename RT> 435 friend inline constexpr T PURE distance2(const VECTOR<T>& lv, const VECTOR<RT>& rv) { 436 return length2(rv - lv); 437 } 438 439 friend inline constexpr VECTOR<T> PURE normalize(const VECTOR<T>& lv) { 440 return lv * (T(1) / length(lv)); 441 } 442 443 friend inline constexpr VECTOR<T> PURE rcp(VECTOR<T> v) { 444 return T(1) / v; 445 } 446 447 friend inline CONSTEXPR VECTOR<T> PURE abs(VECTOR<T> v) { 448 for (size_t i = 0; i < v.size(); i++) { 449 v[i] = std::abs(v[i]); 450 } 451 return v; 452 } 453 454 friend inline CONSTEXPR VECTOR<T> PURE floor(VECTOR<T> v) { 455 for (size_t i = 0; i < v.size(); i++) { 456 v[i] = std::floor(v[i]); 457 } 458 return v; 459 } 460 461 friend inline CONSTEXPR VECTOR<T> PURE ceil(VECTOR<T> v) { 462 for (size_t i = 0; i < v.size(); i++) { 463 v[i] = std::ceil(v[i]); 464 } 465 return v; 466 } 467 468 friend inline CONSTEXPR VECTOR<T> PURE round(VECTOR<T> v) { 469 for (size_t i = 0; i < v.size(); i++) { 470 v[i] = std::round(v[i]); 471 } 472 return v; 473 } 474 475 friend inline CONSTEXPR VECTOR<T> PURE inversesqrt(VECTOR<T> v) { 476 for (size_t i = 0; i < v.size(); i++) { 477 v[i] = T(1) / std::sqrt(v[i]); 478 } 479 return v; 480 } 481 482 friend inline CONSTEXPR VECTOR<T> PURE sqrt(VECTOR<T> v) { 483 for (size_t i = 0; i < v.size(); i++) { 484 v[i] = std::sqrt(v[i]); 485 } 486 return v; 487 } 488 489 friend inline CONSTEXPR VECTOR<T> PURE pow(VECTOR<T> v, T p) { 490 for (size_t i = 0; i < v.size(); i++) { 491 v[i] = std::pow(v[i], p); 492 } 493 return v; 494 } 495 496 friend inline CONSTEXPR VECTOR<T> PURE saturate(const VECTOR<T>& lv) { 497 return clamp(lv, T(0), T(1)); 498 } 499 500 friend inline CONSTEXPR VECTOR<T> PURE clamp(VECTOR<T> v, T min, T max) { 501 for (size_t i = 0; i< v.size(); i++) { 502 v[i] = std::min(max, std::max(min, v[i])); 503 } 504 return v; 505 } 506 507 friend inline CONSTEXPR VECTOR<T> PURE fma(const VECTOR<T>& lv, const VECTOR<T>& rv, VECTOR<T> a) { 508 for (size_t i = 0; i<lv.size(); i++) { 509 //a[i] = std::fma(lv[i], rv[i], a[i]); 510 a[i] += (lv[i] * rv[i]); 511 } 512 return a; 513 } 514 515 friend inline CONSTEXPR VECTOR<T> PURE min(const VECTOR<T>& u, VECTOR<T> v) { 516 for (size_t i = 0; i < v.size(); i++) { 517 v[i] = std::min(u[i], v[i]); 518 } 519 return v; 520 } 521 522 friend inline CONSTEXPR VECTOR<T> PURE max(const VECTOR<T>& u, VECTOR<T> v) { 523 for (size_t i = 0; i < v.size(); i++) { 524 v[i] = std::max(u[i], v[i]); 525 } 526 return v; 527 } 528 529 friend inline CONSTEXPR T PURE max(const VECTOR<T>& v) { 530 T r(std::numeric_limits<T>::lowest()); 531 for (size_t i = 0; i < v.size(); i++) { 532 r = std::max(r, v[i]); 533 } 534 return r; 535 } 536 537 friend inline CONSTEXPR T PURE min(const VECTOR<T>& v) { 538 T r(std::numeric_limits<T>::max()); 539 for (size_t i = 0; i < v.size(); i++) { 540 r = std::min(r, v[i]); 541 } 542 return r; 543 } 544 545 friend inline CONSTEXPR VECTOR<T> PURE apply(VECTOR<T> v, const std::function<T(T)>& f) { 546 for (size_t i = 0; i < v.size(); i++) { 547 v[i] = f(v[i]); 548 } 549 return v; 550 } 551 552 friend inline CONSTEXPR bool PURE any(const VECTOR<T>& v) { 553 for (size_t i = 0; i < v.size(); i++) { 554 if (v[i] != T(0)) return true; 555 } 556 return false; 557 } 558 559 friend inline CONSTEXPR bool PURE all(const VECTOR<T>& v) { 560 bool result = true; 561 for (size_t i = 0; i < v.size(); i++) { 562 result &= (v[i] != T(0)); 563 } 564 return result; 565 } 566 567 template<typename R> 568 friend inline CONSTEXPR VECTOR<R> PURE map(VECTOR<T> v, const std::function<R(T)>& f) { 569 VECTOR<R> result; 570 for (size_t i = 0; i < v.size(); i++) { 571 result[i] = f(v[i]); 572 } 573 return result; 574 } 575}; 576 577/* 578 * TVecDebug implements functions on a vector of type BASE<T>. 579 * 580 * BASE only needs to implement operator[] and size(). 581 * By simply inheriting from TVecDebug<BASE, T> BASE will automatically 582 * get all the functionality here. 583 */ 584template<template<typename T> class VECTOR, typename T> 585class TVecDebug { 586public: 587 /* 588 * NOTE: the functions below ARE NOT member methods. They are friend functions 589 * with they definition inlined with their declaration. This makes these 590 * template functions available to the compiler when (and only when) this class 591 * is instantiated, at which point they're only templated on the 2nd parameter 592 * (the first one, BASE<T> being known). 593 */ 594 friend std::ostream& operator<<(std::ostream& stream, const VECTOR<T>& v) { 595 stream << "< "; 596 for (size_t i = 0; i < v.size() - 1; i++) { 597 stream << T(v[i]) << ", "; 598 } 599 stream << T(v[v.size() - 1]) << " >"; 600 return stream; 601 } 602}; 603 604#undef CONSTEXPR 605#undef PURE 606 607// ------------------------------------------------------------------------------------- 608} // namespace details 609} // namespace android 610 611 612#endif // UI_TVECHELPERS_H_ 613