1/////////////////////////////////////////////////////////////////////////////////// 2/// OpenGL Mathematics (glm.g-truc.net) 3/// 4/// Copyright (c) 2005 - 2014 G-Truc Creation (www.g-truc.net) 5/// Permission is hereby granted, free of charge, to any person obtaining a copy 6/// of this software and associated documentation files (the "Software"), to deal 7/// in the Software without restriction, including without limitation the rights 8/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9/// copies of the Software, and to permit persons to whom the Software is 10/// furnished to do so, subject to the following conditions: 11/// 12/// The above copyright notice and this permission notice shall be included in 13/// all copies or substantial portions of the Software. 14/// 15/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21/// THE SOFTWARE. 22/// 23/// @ref core 24/// @file glm/core/func_common.inl 25/// @date 2008-08-03 / 2011-06-15 26/// @author Christophe Riccio 27/////////////////////////////////////////////////////////////////////////////////// 28 29#include "func_vector_relational.hpp" 30#include "type_vec2.hpp" 31#include "type_vec3.hpp" 32#include "type_vec4.hpp" 33#include "_vectorize.hpp" 34#include <limits> 35 36namespace glm{ 37namespace detail 38{ 39 template <typename genFIType, bool /*signed*/> 40 struct compute_abs 41 {}; 42 43 template <typename genFIType> 44 struct compute_abs<genFIType, true> 45 { 46 GLM_FUNC_QUALIFIER static genFIType call(genFIType const & x) 47 { 48 GLM_STATIC_ASSERT( 49 std::numeric_limits<genFIType>::is_iec559 || std::numeric_limits<genFIType>::is_signed, 50 "'abs' only accept floating-point and integer scalar or vector inputs"); 51 return x >= genFIType(0) ? x : -x; 52 // TODO, perf comp with: *(((int *) &x) + 1) &= 0x7fffffff; 53 } 54 }; 55 56 template <typename genFIType> 57 struct compute_abs<genFIType, false> 58 { 59 GLM_FUNC_QUALIFIER static genFIType call(genFIType const & x) 60 { 61 GLM_STATIC_ASSERT( 62 !std::numeric_limits<genFIType>::is_signed && std::numeric_limits<genFIType>::is_integer, 63 "'abs' only accept floating-point and integer scalar or vector inputs"); 64 return x; 65 } 66 }; 67 68 template <typename T, typename U, precision P, template <class, precision> class vecType> 69 struct compute_mix_vector 70 { 71 GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & x, vecType<T, P> const & y, vecType<U, P> const & a) 72 { 73 GLM_STATIC_ASSERT(std::numeric_limits<U>::is_iec559, "'mix' only accept floating-point inputs for the interpolator a"); 74 75 return vecType<T, P>(vecType<U, P>(x) + a * vecType<U, P>(y - x)); 76 } 77 }; 78 79 template <typename T, precision P, template <class, precision> class vecType> 80 struct compute_mix_vector<T, bool, P, vecType> 81 { 82 GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & x, vecType<T, P> const & y, vecType<bool, P> const & a) 83 { 84 vecType<T, P> Result; 85 for(length_t i = 0; i < x.length(); ++i) 86 Result[i] = a[i] ? y[i] : x[i]; 87 return Result; 88 } 89 }; 90 91 template <typename T, typename U, precision P, template <class, precision> class vecType> 92 struct compute_mix_scalar 93 { 94 GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & x, vecType<T, P> const & y, U const & a) 95 { 96 GLM_STATIC_ASSERT(std::numeric_limits<U>::is_iec559, "'mix' only accept floating-point inputs for the interpolator a"); 97 98 return vecType<T, P>(vecType<U, P>(x) + a * vecType<U, P>(y - x)); 99 } 100 }; 101 102 template <typename T, precision P, template <class, precision> class vecType> 103 struct compute_mix_scalar<T, bool, P, vecType> 104 { 105 GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & x, vecType<T, P> const & y, bool const & a) 106 { 107 return a ? y : x; 108 } 109 }; 110 111 template <typename T, typename U> 112 struct compute_mix 113 { 114 GLM_FUNC_QUALIFIER static T call(T const & x, T const & y, U const & a) 115 { 116 GLM_STATIC_ASSERT(std::numeric_limits<U>::is_iec559, "'mix' only accept floating-point inputs for the interpolator a"); 117 118 return static_cast<T>(static_cast<U>(x) + a * static_cast<U>(y - x)); 119 } 120 }; 121 122 template <typename T> 123 struct compute_mix<T, bool> 124 { 125 GLM_FUNC_QUALIFIER static T call(T const & x, T const & y, bool const & a) 126 { 127 return a ? y : x; 128 } 129 }; 130}//namespace detail 131 132 // abs 133 template <typename genFIType> 134 GLM_FUNC_QUALIFIER genFIType abs 135 ( 136 genFIType const & x 137 ) 138 { 139 return detail::compute_abs<genFIType, std::numeric_limits<genFIType>::is_signed>::call(x); 140 } 141 142 VECTORIZE_VEC(abs) 143 144 // sign 145 //Try something like based on x >> 31 to get the sign bit 146 template <typename genFIType> 147 GLM_FUNC_QUALIFIER genFIType sign 148 ( 149 genFIType const & x 150 ) 151 { 152 GLM_STATIC_ASSERT( 153 std::numeric_limits<genFIType>::is_iec559 || 154 (std::numeric_limits<genFIType>::is_signed && std::numeric_limits<genFIType>::is_integer), "'sign' only accept signed inputs"); 155 156 genFIType result; 157 if(x > genFIType(0)) 158 result = genFIType(1); 159 else if(x < genFIType(0)) 160 result = genFIType(-1); 161 else 162 result = genFIType(0); 163 return result; 164 } 165 166 VECTORIZE_VEC(sign) 167 168 // floor 169 template <typename genType> 170 GLM_FUNC_QUALIFIER genType floor(genType const & x) 171 { 172 GLM_STATIC_ASSERT( 173 std::numeric_limits<genType>::is_iec559, 174 "'floor' only accept floating-point inputs"); 175 176 return ::std::floor(x); 177 } 178 179 VECTORIZE_VEC(floor) 180 181 // trunc 182 template <typename genType> 183 GLM_FUNC_QUALIFIER genType trunc(genType const & x) 184 { 185 GLM_STATIC_ASSERT( 186 std::numeric_limits<genType>::is_iec559, 187 "'trunc' only accept floating-point inputs"); 188 189 // TODO, add C++11 std::trunk 190 return x < 0 ? -floor(-x) : floor(x); 191 } 192 193 VECTORIZE_VEC(trunc) 194 195 // round 196 template <typename genType> 197 GLM_FUNC_QUALIFIER genType round(genType const& x) 198 { 199 GLM_STATIC_ASSERT( 200 std::numeric_limits<genType>::is_iec559, 201 "'round' only accept floating-point inputs"); 202 203 // TODO, add C++11 std::round 204 return x < 0 ? genType(int(x - genType(0.5))) : genType(int(x + genType(0.5))); 205 } 206 207 VECTORIZE_VEC(round) 208 209/* 210 // roundEven 211 template <typename genType> 212 GLM_FUNC_QUALIFIER genType roundEven(genType const& x) 213 { 214 GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'roundEven' only accept floating-point inputs"); 215 216 return genType(int(x + genType(int(x) % 2))); 217 } 218*/ 219 220 // roundEven 221 template <typename genType> 222 GLM_FUNC_QUALIFIER genType roundEven(genType const & x) 223 { 224 GLM_STATIC_ASSERT( 225 std::numeric_limits<genType>::is_iec559, 226 "'roundEven' only accept floating-point inputs"); 227 228 int Integer = static_cast<int>(x); 229 genType IntegerPart = static_cast<genType>(Integer); 230 genType FractionalPart = fract(x); 231 232 if(FractionalPart > static_cast<genType>(0.5) || FractionalPart < static_cast<genType>(0.5)) 233 { 234 return round(x); 235 } 236 else if((Integer % 2) == 0) 237 { 238 return IntegerPart; 239 } 240 else if(x <= static_cast<genType>(0)) // Work around... 241 { 242 return IntegerPart - static_cast<genType>(1); 243 } 244 else 245 { 246 return IntegerPart + static_cast<genType>(1); 247 } 248 //else // Bug on MinGW 4.5.2 249 //{ 250 // return mix(IntegerPart + genType(-1), IntegerPart + genType(1), x <= genType(0)); 251 //} 252 } 253 254 VECTORIZE_VEC(roundEven) 255 256 // ceil 257 template <typename genType> 258 GLM_FUNC_QUALIFIER genType ceil(genType const & x) 259 { 260 GLM_STATIC_ASSERT( 261 std::numeric_limits<genType>::is_iec559, 262 "'ceil' only accept floating-point inputs"); 263 264 return ::std::ceil(x); 265 } 266 267 VECTORIZE_VEC(ceil) 268 269 // fract 270 template <typename genType> 271 GLM_FUNC_QUALIFIER genType fract 272 ( 273 genType const & x 274 ) 275 { 276 GLM_STATIC_ASSERT( 277 std::numeric_limits<genType>::is_iec559, 278 "'fract' only accept floating-point inputs"); 279 280 return x - floor(x); 281 } 282 283 VECTORIZE_VEC(fract) 284 285 // mod 286 template <typename genType> 287 GLM_FUNC_QUALIFIER genType mod 288 ( 289 genType const & x, 290 genType const & y 291 ) 292 { 293 GLM_STATIC_ASSERT( 294 std::numeric_limits<genType>::is_iec559, 295 "'mod' only accept floating-point inputs"); 296 297 return x - y * floor(x / y); 298 } 299 300 VECTORIZE_VEC_SCA(mod) 301 VECTORIZE_VEC_VEC(mod) 302 303 // modf 304 template <typename genType> 305 GLM_FUNC_QUALIFIER genType modf 306 ( 307 genType const & x, 308 genType & i 309 ) 310 { 311 GLM_STATIC_ASSERT( 312 std::numeric_limits<genType>::is_iec559, 313 "'modf' only accept floating-point inputs"); 314 315 return std::modf(x, &i); 316 } 317 318 template <typename T, precision P> 319 GLM_FUNC_QUALIFIER detail::tvec2<T, P> modf 320 ( 321 detail::tvec2<T, P> const & x, 322 detail::tvec2<T, P> & i 323 ) 324 { 325 return detail::tvec2<T, P>( 326 modf(x.x, i.x), 327 modf(x.y, i.y)); 328 } 329 330 template <typename T, precision P> 331 GLM_FUNC_QUALIFIER detail::tvec3<T, P> modf 332 ( 333 detail::tvec3<T, P> const & x, 334 detail::tvec3<T, P> & i 335 ) 336 { 337 return detail::tvec3<T, P>( 338 modf(x.x, i.x), 339 modf(x.y, i.y), 340 modf(x.z, i.z)); 341 } 342 343 template <typename T, precision P> 344 GLM_FUNC_QUALIFIER detail::tvec4<T, P> modf 345 ( 346 detail::tvec4<T, P> const & x, 347 detail::tvec4<T, P> & i 348 ) 349 { 350 return detail::tvec4<T, P>( 351 modf(x.x, i.x), 352 modf(x.y, i.y), 353 modf(x.z, i.z), 354 modf(x.w, i.w)); 355 } 356 357 //// Only valid if (INT_MIN <= x-y <= INT_MAX) 358 //// min(x,y) 359 //r = y + ((x - y) & ((x - y) >> (sizeof(int) * 360 //CHAR_BIT - 1))); 361 //// max(x,y) 362 //r = x - ((x - y) & ((x - y) >> (sizeof(int) * 363 //CHAR_BIT - 1))); 364 365 // min 366 template <typename genType> 367 GLM_FUNC_QUALIFIER genType min 368 ( 369 genType const & x, 370 genType const & y 371 ) 372 { 373 GLM_STATIC_ASSERT( 374 std::numeric_limits<genType>::is_iec559 || std::numeric_limits<genType>::is_integer, 375 "'min' only accept floating-point or integer inputs"); 376 377 return x < y ? x : y; 378 } 379 380 VECTORIZE_VEC_SCA(min) 381 VECTORIZE_VEC_VEC(min) 382 383 // max 384 template <typename genType> 385 GLM_FUNC_QUALIFIER genType max 386 ( 387 genType const & x, 388 genType const & y 389 ) 390 { 391 GLM_STATIC_ASSERT( 392 std::numeric_limits<genType>::is_iec559 || std::numeric_limits<genType>::is_integer, 393 "'max' only accept floating-point or integer inputs"); 394 395 return x > y ? x : y; 396 } 397 398 VECTORIZE_VEC_SCA(max) 399 VECTORIZE_VEC_VEC(max) 400 401 // clamp 402 template <typename genType> 403 GLM_FUNC_QUALIFIER genType clamp 404 ( 405 genType const & x, 406 genType const & minVal, 407 genType const & maxVal 408 ) 409 { 410 GLM_STATIC_ASSERT( 411 std::numeric_limits<genType>::is_iec559 || std::numeric_limits<genType>::is_integer, 412 "'clamp' only accept floating-point or integer inputs"); 413 414 return min(maxVal, max(minVal, x)); 415 } 416 417 template <typename T, precision P> 418 GLM_FUNC_QUALIFIER detail::tvec2<T, P> clamp 419 ( 420 detail::tvec2<T, P> const & x, 421 T const & minVal, 422 T const & maxVal 423 ) 424 { 425 GLM_STATIC_ASSERT( 426 std::numeric_limits<T>::is_iec559 || std::numeric_limits<T>::is_integer, 427 "'clamp' only accept floating-point or integer inputs"); 428 429 return detail::tvec2<T, P>( 430 clamp(x.x, minVal, maxVal), 431 clamp(x.y, minVal, maxVal)); 432 } 433 434 template <typename T, precision P> 435 GLM_FUNC_QUALIFIER detail::tvec3<T, P> clamp 436 ( 437 detail::tvec3<T, P> const & x, 438 T const & minVal, 439 T const & maxVal 440 ) 441 { 442 GLM_STATIC_ASSERT( 443 std::numeric_limits<T>::is_iec559 || std::numeric_limits<T>::is_integer, 444 "'clamp' only accept floating-point or integer inputs"); 445 446 return detail::tvec3<T, P>( 447 clamp(x.x, minVal, maxVal), 448 clamp(x.y, minVal, maxVal), 449 clamp(x.z, minVal, maxVal)); 450 } 451 452 template <typename T, precision P> 453 GLM_FUNC_QUALIFIER detail::tvec4<T, P> clamp 454 ( 455 detail::tvec4<T, P> const & x, 456 T const & minVal, 457 T const & maxVal 458 ) 459 { 460 GLM_STATIC_ASSERT( 461 std::numeric_limits<T>::is_iec559 || std::numeric_limits<T>::is_integer, 462 "'clamp' only accept floating-point or integer inputs"); 463 464 return detail::tvec4<T, P>( 465 clamp(x.x, minVal, maxVal), 466 clamp(x.y, minVal, maxVal), 467 clamp(x.z, minVal, maxVal), 468 clamp(x.w, minVal, maxVal)); 469 } 470 471 template <typename T, precision P> 472 GLM_FUNC_QUALIFIER detail::tvec2<T, P> clamp 473 ( 474 detail::tvec2<T, P> const & x, 475 detail::tvec2<T, P> const & minVal, 476 detail::tvec2<T, P> const & maxVal 477 ) 478 { 479 GLM_STATIC_ASSERT( 480 std::numeric_limits<T>::is_iec559 || std::numeric_limits<T>::is_integer, 481 "'clamp' only accept floating-point or integer inputs"); 482 483 return detail::tvec2<T, P>( 484 clamp(x.x, minVal.x, maxVal.x), 485 clamp(x.y, minVal.y, maxVal.y)); 486 } 487 488 template <typename T, precision P> 489 GLM_FUNC_QUALIFIER detail::tvec3<T, P> clamp 490 ( 491 detail::tvec3<T, P> const & x, 492 detail::tvec3<T, P> const & minVal, 493 detail::tvec3<T, P> const & maxVal 494 ) 495 { 496 GLM_STATIC_ASSERT( 497 std::numeric_limits<T>::is_iec559 || std::numeric_limits<T>::is_integer, 498 "'clamp' only accept floating-point or integer inputs"); 499 500 return detail::tvec3<T, P>( 501 clamp(x.x, minVal.x, maxVal.x), 502 clamp(x.y, minVal.y, maxVal.y), 503 clamp(x.z, minVal.z, maxVal.z)); 504 } 505 506 template <typename T, precision P> 507 GLM_FUNC_QUALIFIER detail::tvec4<T, P> clamp 508 ( 509 detail::tvec4<T, P> const & x, 510 detail::tvec4<T, P> const & minVal, 511 detail::tvec4<T, P> const & maxVal 512 ) 513 { 514 GLM_STATIC_ASSERT( 515 std::numeric_limits<T>::is_iec559 || std::numeric_limits<T>::is_integer, 516 "'clamp' only accept floating-point or integer inputs"); 517 518 return detail::tvec4<T, P>( 519 clamp(x.x, minVal.x, maxVal.x), 520 clamp(x.y, minVal.y, maxVal.y), 521 clamp(x.z, minVal.z, maxVal.z), 522 clamp(x.w, minVal.w, maxVal.w)); 523 } 524 525 template <typename T, typename U, precision P, template <typename, precision> class vecType> 526 GLM_FUNC_QUALIFIER vecType<T, P> mix 527 ( 528 vecType<T, P> const & x, 529 vecType<T, P> const & y, 530 vecType<U, P> const & a 531 ) 532 { 533 return detail::compute_mix_vector<T, U, P, vecType>::call(x, y, a); 534 } 535 536 template <typename T, typename U, precision P, template <typename, precision> class vecType> 537 GLM_FUNC_QUALIFIER vecType<T, P> mix 538 ( 539 vecType<T, P> const & x, 540 vecType<T, P> const & y, 541 U const & a 542 ) 543 { 544 return detail::compute_mix_scalar<T, U, P, vecType>::call(x, y, a); 545 } 546 547 template <typename genTypeT, typename genTypeU> 548 GLM_FUNC_QUALIFIER genTypeT mix 549 ( 550 genTypeT const & x, 551 genTypeT const & y, 552 genTypeU const & a 553 ) 554 { 555 return detail::compute_mix<genTypeT, genTypeU>::call(x, y, a); 556 } 557 558 // step 559 template <typename genType> 560 GLM_FUNC_QUALIFIER genType step 561 ( 562 genType const & edge, 563 genType const & x 564 ) 565 { 566 return mix(genType(1), genType(0), glm::lessThan(x, edge)); 567 } 568 569 template <template <typename, precision> class vecType, typename T, precision P> 570 GLM_FUNC_QUALIFIER vecType<T, P> step 571 ( 572 T const & edge, 573 vecType<T, P> const & x 574 ) 575 { 576 GLM_STATIC_ASSERT( 577 std::numeric_limits<T>::is_iec559, 578 "'step' only accept floating-point inputs"); 579 580 return mix(vecType<T, P>(1), vecType<T, P>(0), glm::lessThan(x, vecType<T, P>(edge))); 581 } 582 583 // smoothstep 584 template <typename genType> 585 GLM_FUNC_QUALIFIER genType smoothstep 586 ( 587 genType const & edge0, 588 genType const & edge1, 589 genType const & x 590 ) 591 { 592 GLM_STATIC_ASSERT( 593 std::numeric_limits<genType>::is_iec559, 594 "'smoothstep' only accept floating-point inputs"); 595 596 genType tmp = clamp((x - edge0) / (edge1 - edge0), genType(0), genType(1)); 597 return tmp * tmp * (genType(3) - genType(2) * tmp); 598 } 599 600 template <typename T, precision P> 601 GLM_FUNC_QUALIFIER detail::tvec2<T, P> smoothstep 602 ( 603 T const & edge0, 604 T const & edge1, 605 detail::tvec2<T, P> const & x 606 ) 607 { 608 GLM_STATIC_ASSERT( 609 std::numeric_limits<T>::is_iec559, 610 "'smoothstep' only accept floating-point inputs"); 611 612 return detail::tvec2<T, P>( 613 smoothstep(edge0, edge1, x.x), 614 smoothstep(edge0, edge1, x.y)); 615 } 616 617 template <typename T, precision P> 618 GLM_FUNC_QUALIFIER detail::tvec3<T, P> smoothstep 619 ( 620 T const & edge0, 621 T const & edge1, 622 detail::tvec3<T, P> const & x 623 ) 624 { 625 GLM_STATIC_ASSERT( 626 std::numeric_limits<T>::is_iec559, 627 "'smoothstep' only accept floating-point inputs"); 628 629 return detail::tvec3<T, P>( 630 smoothstep(edge0, edge1, x.x), 631 smoothstep(edge0, edge1, x.y), 632 smoothstep(edge0, edge1, x.z)); 633 } 634 635 template <typename T, precision P> 636 GLM_FUNC_QUALIFIER detail::tvec4<T, P> smoothstep 637 ( 638 T const & edge0, 639 T const & edge1, 640 detail::tvec4<T, P> const & x 641 ) 642 { 643 GLM_STATIC_ASSERT( 644 std::numeric_limits<T>::is_iec559, 645 "'smoothstep' only accept floating-point inputs"); 646 647 return detail::tvec4<T, P>( 648 smoothstep(edge0, edge1, x.x), 649 smoothstep(edge0, edge1, x.y), 650 smoothstep(edge0, edge1, x.z), 651 smoothstep(edge0, edge1, x.w)); 652 } 653 654 template <typename T, precision P> 655 GLM_FUNC_QUALIFIER detail::tvec2<T, P> smoothstep 656 ( 657 detail::tvec2<T, P> const & edge0, 658 detail::tvec2<T, P> const & edge1, 659 detail::tvec2<T, P> const & x 660 ) 661 { 662 GLM_STATIC_ASSERT( 663 std::numeric_limits<T>::is_iec559, 664 "'smoothstep' only accept floating-point inputs"); 665 666 return detail::tvec2<T, P>( 667 smoothstep(edge0.x, edge1.x, x.x), 668 smoothstep(edge0.y, edge1.y, x.y)); 669 } 670 671 template <typename T, precision P> 672 GLM_FUNC_QUALIFIER detail::tvec3<T, P> smoothstep 673 ( 674 detail::tvec3<T, P> const & edge0, 675 detail::tvec3<T, P> const & edge1, 676 detail::tvec3<T, P> const & x 677 ) 678 { 679 GLM_STATIC_ASSERT( 680 std::numeric_limits<T>::is_iec559, 681 "'smoothstep' only accept floating-point inputs"); 682 683 return detail::tvec3<T, P>( 684 smoothstep(edge0.x, edge1.x, x.x), 685 smoothstep(edge0.y, edge1.y, x.y), 686 smoothstep(edge0.z, edge1.z, x.z)); 687 } 688 689 template <typename T, precision P> 690 GLM_FUNC_QUALIFIER detail::tvec4<T, P> smoothstep 691 ( 692 detail::tvec4<T, P> const & edge0, 693 detail::tvec4<T, P> const & edge1, 694 detail::tvec4<T, P> const & x 695 ) 696 { 697 GLM_STATIC_ASSERT( 698 std::numeric_limits<T>::is_iec559, 699 "'smoothstep' only accept floating-point inputs"); 700 701 return detail::tvec4<T, P>( 702 smoothstep(edge0.x, edge1.x, x.x), 703 smoothstep(edge0.y, edge1.y, x.y), 704 smoothstep(edge0.z, edge1.z, x.z), 705 smoothstep(edge0.w, edge1.w, x.w)); 706 } 707 708 // TODO: Not working on MinGW... 709 template <typename genType> 710 GLM_FUNC_QUALIFIER bool isnan(genType const & x) 711 { 712 GLM_STATIC_ASSERT( 713 std::numeric_limits<genType>::is_iec559, 714 "'isnan' only accept floating-point inputs"); 715 716# if(GLM_COMPILER & (GLM_COMPILER_VC | GLM_COMPILER_INTEL)) 717 return _isnan(x) != 0; 718# elif(GLM_COMPILER & (GLM_COMPILER_GCC | GLM_COMPILER_CLANG)) 719# if(GLM_PLATFORM & GLM_PLATFORM_ANDROID) 720 return _isnan(x) != 0; 721# else 722 return std::isnan(x); 723# endif 724# elif(GLM_COMPILER & GLM_COMPILER_CUDA) 725 return isnan(x) != 0; 726# else 727 return std::isnan(x); 728# endif 729 } 730 731 template <typename T, precision P> 732 GLM_FUNC_QUALIFIER typename detail::tvec2<T, P>::bool_type isnan 733 ( 734 detail::tvec2<T, P> const & x 735 ) 736 { 737 GLM_STATIC_ASSERT( 738 std::numeric_limits<T>::is_iec559, 739 "'isnan' only accept floating-point inputs"); 740 741 return typename detail::tvec2<T, P>::bool_type( 742 isnan(x.x), 743 isnan(x.y)); 744 } 745 746 template <typename T, precision P> 747 GLM_FUNC_QUALIFIER typename detail::tvec3<T, P>::bool_type isnan 748 ( 749 detail::tvec3<T, P> const & x 750 ) 751 { 752 GLM_STATIC_ASSERT( 753 std::numeric_limits<T>::is_iec559, 754 "'isnan' only accept floating-point inputs"); 755 756 return typename detail::tvec3<T, P>::bool_type( 757 isnan(x.x), 758 isnan(x.y), 759 isnan(x.z)); 760 } 761 762 template <typename T, precision P> 763 GLM_FUNC_QUALIFIER typename detail::tvec4<T, P>::bool_type isnan 764 ( 765 detail::tvec4<T, P> const & x 766 ) 767 { 768 GLM_STATIC_ASSERT( 769 std::numeric_limits<T>::is_iec559, 770 "'isnan' only accept floating-point inputs"); 771 772 return typename detail::tvec4<T, P>::bool_type( 773 isnan(x.x), 774 isnan(x.y), 775 isnan(x.z), 776 isnan(x.w)); 777 } 778 779 template <typename genType> 780 GLM_FUNC_QUALIFIER bool isinf( 781 genType const & x) 782 { 783 GLM_STATIC_ASSERT( 784 std::numeric_limits<genType>::is_iec559, 785 "'isinf' only accept floating-point inputs"); 786 787# if(GLM_COMPILER & (GLM_COMPILER_INTEL | GLM_COMPILER_VC)) 788 return _fpclass(x) == _FPCLASS_NINF || _fpclass(x) == _FPCLASS_PINF; 789# elif(GLM_COMPILER & (GLM_COMPILER_GCC | GLM_COMPILER_CLANG)) 790# if(GLM_PLATFORM & GLM_PLATFORM_ANDROID) 791 return _isinf(x) != 0; 792# else 793 return std::isinf(x); 794# endif 795# elif(GLM_COMPILER & GLM_COMPILER_CUDA) 796 // http://developer.download.nvidia.com/compute/cuda/4_2/rel/toolkit/docs/online/group__CUDA__MATH__DOUBLE_g13431dd2b40b51f9139cbb7f50c18fab.html#g13431dd2b40b51f9139cbb7f50c18fab 797 return isinf(double(x)) != 0; 798# else 799 return std::isinf(x); 800# endif 801 } 802 803 template <typename T, precision P> 804 GLM_FUNC_QUALIFIER typename detail::tvec2<T, P>::bool_type isinf 805 ( 806 detail::tvec2<T, P> const & x 807 ) 808 { 809 GLM_STATIC_ASSERT( 810 std::numeric_limits<T>::is_iec559, 811 "'isinf' only accept floating-point inputs"); 812 813 return typename detail::tvec2<T, P>::bool_type( 814 isinf(x.x), 815 isinf(x.y)); 816 } 817 818 template <typename T, precision P> 819 GLM_FUNC_QUALIFIER typename detail::tvec3<T, P>::bool_type isinf 820 ( 821 detail::tvec3<T, P> const & x 822 ) 823 { 824 GLM_STATIC_ASSERT( 825 std::numeric_limits<T>::is_iec559, 826 "'isinf' only accept floating-point inputs"); 827 828 return typename detail::tvec3<T, P>::bool_type( 829 isinf(x.x), 830 isinf(x.y), 831 isinf(x.z)); 832 } 833 834 template <typename T, precision P> 835 GLM_FUNC_QUALIFIER typename detail::tvec4<T, P>::bool_type isinf 836 ( 837 detail::tvec4<T, P> const & x 838 ) 839 { 840 GLM_STATIC_ASSERT( 841 std::numeric_limits<T>::is_iec559, 842 "'isinf' only accept floating-point inputs"); 843 844 return typename detail::tvec4<T, P>::bool_type( 845 isinf(x.x), 846 isinf(x.y), 847 isinf(x.z), 848 isinf(x.w)); 849 } 850 851 GLM_FUNC_QUALIFIER int floatBitsToInt(float const & v) 852 { 853 return reinterpret_cast<int&>(const_cast<float&>(v)); 854 } 855 856 template <template <typename, precision> class vecType, precision P> 857 GLM_FUNC_QUALIFIER vecType<int, P> floatBitsToInt(vecType<float, P> const & v) 858 { 859 return reinterpret_cast<vecType<int, P>&>(const_cast<vecType<float, P>&>(v)); 860 } 861 862 GLM_FUNC_QUALIFIER uint floatBitsToUint(float const & v) 863 { 864 return reinterpret_cast<uint&>(const_cast<float&>(v)); 865 } 866 867 template <template <typename, precision> class vecType, precision P> 868 GLM_FUNC_QUALIFIER vecType<uint, P> floatBitsToUint(vecType<float, P> const & v) 869 { 870 return reinterpret_cast<vecType<uint, P>&>(const_cast<vecType<float, P>&>(v)); 871 } 872 873 GLM_FUNC_QUALIFIER float intBitsToFloat(int const & v) 874 { 875 return reinterpret_cast<float&>(const_cast<int&>(v)); 876 } 877 878 template <template <typename, precision> class vecType, precision P> 879 GLM_FUNC_QUALIFIER vecType<float, P> intBitsToFloat(vecType<int, P> const & v) 880 { 881 return reinterpret_cast<vecType<float, P>&>(const_cast<vecType<int, P>&>(v)); 882 } 883 884 GLM_FUNC_QUALIFIER float uintBitsToFloat(uint const & v) 885 { 886 return reinterpret_cast<float&>(const_cast<uint&>(v)); 887 } 888 889 template <template <typename, precision> class vecType, precision P> 890 GLM_FUNC_QUALIFIER vecType<float, P> uintBitsToFloat(vecType<uint, P> const & v) 891 { 892 return reinterpret_cast<vecType<float, P>&>(const_cast<vecType<uint, P>&>(v)); 893 } 894 895 template <typename genType> 896 GLM_FUNC_QUALIFIER genType fma 897 ( 898 genType const & a, 899 genType const & b, 900 genType const & c 901 ) 902 { 903 return a * b + c; 904 } 905 906 template <typename genType> 907 GLM_FUNC_QUALIFIER genType frexp 908 ( 909 genType const & x, 910 int & exp 911 ) 912 { 913 GLM_STATIC_ASSERT( 914 std::numeric_limits<genType>::is_iec559, 915 "'frexp' only accept floating-point inputs"); 916 917 return std::frexp(x, exp); 918 } 919 920 template <typename T, precision P> 921 GLM_FUNC_QUALIFIER detail::tvec2<T, P> frexp 922 ( 923 detail::tvec2<T, P> const & x, 924 detail::tvec2<int, P> & exp 925 ) 926 { 927 GLM_STATIC_ASSERT( 928 std::numeric_limits<T>::is_iec559, 929 "'frexp' only accept floating-point inputs"); 930 931 return detail::tvec2<T, P>( 932 frexp(x.x, exp.x), 933 frexp(x.y, exp.y)); 934 } 935 936 template <typename T, precision P> 937 GLM_FUNC_QUALIFIER detail::tvec3<T, P> frexp 938 ( 939 detail::tvec3<T, P> const & x, 940 detail::tvec3<int, P> & exp 941 ) 942 { 943 GLM_STATIC_ASSERT( 944 std::numeric_limits<T>::is_iec559, 945 "'frexp' only accept floating-point inputs"); 946 947 return detail::tvec3<T, P>( 948 frexp(x.x, exp.x), 949 frexp(x.y, exp.y), 950 frexp(x.z, exp.z)); 951 } 952 953 template <typename T, precision P> 954 GLM_FUNC_QUALIFIER detail::tvec4<T, P> frexp 955 ( 956 detail::tvec4<T, P> const & x, 957 detail::tvec4<int, P> & exp 958 ) 959 { 960 GLM_STATIC_ASSERT( 961 std::numeric_limits<T>::is_iec559, 962 "'frexp' only accept floating-point inputs"); 963 964 return detail::tvec4<T, P>( 965 frexp(x.x, exp.x), 966 frexp(x.y, exp.y), 967 frexp(x.z, exp.z), 968 frexp(x.w, exp.w)); 969 } 970 971 template <typename genType, precision P> 972 GLM_FUNC_QUALIFIER genType ldexp 973 ( 974 genType const & x, 975 int const & exp 976 ) 977 { 978 GLM_STATIC_ASSERT( 979 std::numeric_limits<genType>::is_iec559, 980 "'frexp' only accept floating-point inputs"); 981 982 return std::ldexp(x, exp); 983 } 984 985 template <typename T, precision P> 986 GLM_FUNC_QUALIFIER detail::tvec2<T, P> ldexp 987 ( 988 detail::tvec2<T, P> const & x, 989 detail::tvec2<int, P> const & exp 990 ) 991 { 992 GLM_STATIC_ASSERT( 993 std::numeric_limits<T>::is_iec559, 994 "'ldexp' only accept floating-point inputs"); 995 996 return detail::tvec2<T, P>( 997 ldexp(x.x, exp.x), 998 ldexp(x.y, exp.y)); 999 } 1000 1001 template <typename T, precision P> 1002 GLM_FUNC_QUALIFIER detail::tvec3<T, P> ldexp 1003 ( 1004 detail::tvec3<T, P> const & x, 1005 detail::tvec3<int, P> const & exp 1006 ) 1007 { 1008 GLM_STATIC_ASSERT( 1009 std::numeric_limits<T>::is_iec559, 1010 "'ldexp' only accept floating-point inputs"); 1011 1012 return detail::tvec3<T, P>( 1013 ldexp(x.x, exp.x), 1014 ldexp(x.y, exp.y), 1015 ldexp(x.z, exp.z)); 1016 } 1017 1018 template <typename T, precision P> 1019 GLM_FUNC_QUALIFIER detail::tvec4<T, P> ldexp 1020 ( 1021 detail::tvec4<T, P> const & x, 1022 detail::tvec4<int, P> const & exp 1023 ) 1024 { 1025 GLM_STATIC_ASSERT( 1026 std::numeric_limits<T>::is_iec559, 1027 "'ldexp' only accept floating-point inputs"); 1028 1029 return detail::tvec4<T, P>( 1030 ldexp(x.x, exp.x), 1031 ldexp(x.y, exp.y), 1032 ldexp(x.z, exp.z), 1033 ldexp(x.w, exp.w)); 1034 } 1035 1036}//namespace glm 1037