1/// @ref core 2/// @file glm/detail/func_common.inl 3 4#include "func_vector_relational.hpp" 5#include "type_vec2.hpp" 6#include "type_vec3.hpp" 7#include "type_vec4.hpp" 8#include "_vectorize.hpp" 9#include <limits> 10 11namespace glm 12{ 13 // min 14 template <typename genType> 15 GLM_FUNC_QUALIFIER genType min(genType x, genType y) 16 { 17 GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559 || std::numeric_limits<genType>::is_integer || GLM_UNRESTRICTED_GENTYPE, "'min' only accept floating-point or integer inputs"); 18 return x < y ? x : y; 19 } 20 21 // max 22 template <typename genType> 23 GLM_FUNC_QUALIFIER genType max(genType x, genType y) 24 { 25 GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559 || std::numeric_limits<genType>::is_integer || GLM_UNRESTRICTED_GENTYPE, "'max' only accept floating-point or integer inputs"); 26 27 return x > y ? x : y; 28 } 29 30 // abs 31 template <> 32 GLM_FUNC_QUALIFIER int32 abs(int32 x) 33 { 34 int32 const y = x >> 31; 35 return (x ^ y) - y; 36 } 37 38 // round 39# if GLM_HAS_CXX11_STL 40 using ::std::round; 41# else 42 template <typename genType> 43 GLM_FUNC_QUALIFIER genType round(genType x) 44 { 45 GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'round' only accept floating-point inputs"); 46 47 return x < static_cast<genType>(0) ? static_cast<genType>(int(x - static_cast<genType>(0.5))) : static_cast<genType>(int(x + static_cast<genType>(0.5))); 48 } 49# endif 50 51 // trunc 52# if GLM_HAS_CXX11_STL 53 using ::std::trunc; 54# else 55 template <typename genType> 56 GLM_FUNC_QUALIFIER genType trunc(genType x) 57 { 58 GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'trunc' only accept floating-point inputs"); 59 60 return x < static_cast<genType>(0) ? -std::floor(-x) : std::floor(x); 61 } 62# endif 63 64}//namespace glm 65 66namespace glm{ 67namespace detail 68{ 69 template <typename genFIType, bool /*signed*/> 70 struct compute_abs 71 {}; 72 73 template <typename genFIType> 74 struct compute_abs<genFIType, true> 75 { 76 GLM_FUNC_QUALIFIER static genFIType call(genFIType x) 77 { 78 GLM_STATIC_ASSERT( 79 std::numeric_limits<genFIType>::is_iec559 || std::numeric_limits<genFIType>::is_signed || GLM_UNRESTRICTED_GENTYPE, 80 "'abs' only accept floating-point and integer scalar or vector inputs"); 81 82 return x >= genFIType(0) ? x : -x; 83 // TODO, perf comp with: *(((int *) &x) + 1) &= 0x7fffffff; 84 } 85 }; 86 87 #if GLM_COMPILER & GLM_COMPILER_CUDA 88 template <> 89 struct compute_abs<float, true> 90 { 91 GLM_FUNC_QUALIFIER static float call(float x) 92 { 93 return fabsf(x); 94 } 95 }; 96 #endif 97 98 template <typename genFIType> 99 struct compute_abs<genFIType, false> 100 { 101 GLM_FUNC_QUALIFIER static genFIType call(genFIType x) 102 { 103 GLM_STATIC_ASSERT( 104 (!std::numeric_limits<genFIType>::is_signed && std::numeric_limits<genFIType>::is_integer) || GLM_UNRESTRICTED_GENTYPE, 105 "'abs' only accept floating-point and integer scalar or vector inputs"); 106 return x; 107 } 108 }; 109 110 template <typename T, precision P, template <typename, precision> class vecType, bool Aligned> 111 struct compute_abs_vector 112 { 113 GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & x) 114 { 115 return detail::functor1<T, T, P, vecType>::call(abs, x); 116 } 117 }; 118 119 template <typename T, typename U, precision P, template <typename, precision> class vecType, bool Aligned> 120 struct compute_mix_vector 121 { 122 GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & x, vecType<T, P> const & y, vecType<U, P> const & a) 123 { 124 GLM_STATIC_ASSERT(std::numeric_limits<U>::is_iec559 || GLM_UNRESTRICTED_GENTYPE, "'mix' only accept floating-point inputs for the interpolator a"); 125 126 return vecType<T, P>(vecType<U, P>(x) + a * vecType<U, P>(y - x)); 127 } 128 }; 129 130 template <typename T, precision P, template <typename, precision> class vecType, bool Aligned> 131 struct compute_mix_vector<T, bool, P, vecType, Aligned> 132 { 133 GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & x, vecType<T, P> const & y, vecType<bool, P> const & a) 134 { 135 vecType<T, P> Result(uninitialize); 136 for(length_t i = 0; i < x.length(); ++i) 137 Result[i] = a[i] ? y[i] : x[i]; 138 return Result; 139 } 140 }; 141 142 template <typename T, typename U, precision P, template <typename, precision> class vecType, bool Aligned> 143 struct compute_mix_scalar 144 { 145 GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & x, vecType<T, P> const & y, U const & a) 146 { 147 GLM_STATIC_ASSERT(std::numeric_limits<U>::is_iec559 || GLM_UNRESTRICTED_GENTYPE, "'mix' only accept floating-point inputs for the interpolator a"); 148 149 return vecType<T, P>(vecType<U, P>(x) + a * vecType<U, P>(y - x)); 150 } 151 }; 152 153 template <typename T, precision P, template <typename, precision> class vecType, bool Aligned> 154 struct compute_mix_scalar<T, bool, P, vecType, Aligned> 155 { 156 GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & x, vecType<T, P> const & y, bool const & a) 157 { 158 return a ? y : x; 159 } 160 }; 161 162 template <typename T, typename U> 163 struct compute_mix 164 { 165 GLM_FUNC_QUALIFIER static T call(T const & x, T const & y, U const & a) 166 { 167 GLM_STATIC_ASSERT(std::numeric_limits<U>::is_iec559 || GLM_UNRESTRICTED_GENTYPE, "'mix' only accept floating-point inputs for the interpolator a"); 168 169 return static_cast<T>(static_cast<U>(x) + a * static_cast<U>(y - x)); 170 } 171 }; 172 173 template <typename T> 174 struct compute_mix<T, bool> 175 { 176 GLM_FUNC_QUALIFIER static T call(T const & x, T const & y, bool const & a) 177 { 178 return a ? y : x; 179 } 180 }; 181 182 template <typename T, precision P, template <typename, precision> class vecType, bool isFloat, bool Aligned> 183 struct compute_sign 184 { 185 GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & x) 186 { 187 return vecType<T, P>(glm::lessThan(vecType<T, P>(0), x)) - vecType<T, P>(glm::lessThan(x, vecType<T, P>(0))); 188 } 189 }; 190 191# if GLM_ARCH == GLM_ARCH_X86 192 template <typename T, precision P, template <typename, precision> class vecType, bool Aligned> 193 struct compute_sign<T, P, vecType, false, Aligned> 194 { 195 GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & x) 196 { 197 T const Shift(static_cast<T>(sizeof(T) * 8 - 1)); 198 vecType<T, P> const y(vecType<typename make_unsigned<T>::type, P>(-x) >> typename make_unsigned<T>::type(Shift)); 199 200 return (x >> Shift) | y; 201 } 202 }; 203# endif 204 205 template <typename T, precision P, template <typename, precision> class vecType, bool Aligned> 206 struct compute_floor 207 { 208 GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & x) 209 { 210 return detail::functor1<T, T, P, vecType>::call(std::floor, x); 211 } 212 }; 213 214 template <typename T, precision P, template <typename, precision> class vecType, bool Aligned> 215 struct compute_ceil 216 { 217 GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & x) 218 { 219 return detail::functor1<T, T, P, vecType>::call(std::ceil, x); 220 } 221 }; 222 223 template <typename T, precision P, template <typename, precision> class vecType, bool Aligned> 224 struct compute_fract 225 { 226 GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & x) 227 { 228 return x - floor(x); 229 } 230 }; 231 232 template <typename T, precision P, template <typename, precision> class vecType, bool Aligned> 233 struct compute_trunc 234 { 235 GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & x) 236 { 237 return detail::functor1<T, T, P, vecType>::call(trunc, x); 238 } 239 }; 240 241 template <typename T, precision P, template <typename, precision> class vecType, bool Aligned> 242 struct compute_round 243 { 244 GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & x) 245 { 246 return detail::functor1<T, T, P, vecType>::call(round, x); 247 } 248 }; 249 250 template <typename T, precision P, template <typename, precision> class vecType, bool Aligned> 251 struct compute_mod 252 { 253 GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & a, vecType<T, P> const & b) 254 { 255 GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'mod' only accept floating-point inputs. Include <glm/gtc/integer.hpp> for integer inputs."); 256 return a - b * floor(a / b); 257 } 258 }; 259 260 template <typename T, precision P, template <typename, precision> class vecType, bool Aligned> 261 struct compute_min_vector 262 { 263 GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & x, vecType<T, P> const & y) 264 { 265 return detail::functor2<T, P, vecType>::call(min, x, y); 266 } 267 }; 268 269 template <typename T, precision P, template <typename, precision> class vecType, bool Aligned> 270 struct compute_max_vector 271 { 272 GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & x, vecType<T, P> const & y) 273 { 274 return detail::functor2<T, P, vecType>::call(max, x, y); 275 } 276 }; 277 278 template <typename T, precision P, template <typename, precision> class vecType, bool Aligned> 279 struct compute_clamp_vector 280 { 281 GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & x, vecType<T, P> const & minVal, vecType<T, P> const & maxVal) 282 { 283 return min(max(x, minVal), maxVal); 284 } 285 }; 286 287 template <typename T, precision P, template <typename, precision> class vecType, bool Aligned> 288 struct compute_step_vector 289 { 290 GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & edge, vecType<T, P> const & x) 291 { 292 return mix(vecType<T, P>(1), vecType<T, P>(0), glm::lessThan(x, edge)); 293 } 294 }; 295 296 template <typename T, precision P, template <typename, precision> class vecType, bool Aligned> 297 struct compute_smoothstep_vector 298 { 299 GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & edge0, vecType<T, P> const & edge1, vecType<T, P> const & x) 300 { 301 GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559 || GLM_UNRESTRICTED_GENTYPE, "'step' only accept floating-point inputs"); 302 vecType<T, P> const tmp(clamp((x - edge0) / (edge1 - edge0), static_cast<T>(0), static_cast<T>(1))); 303 return tmp * tmp * (static_cast<T>(3) - static_cast<T>(2) * tmp); 304 } 305 }; 306}//namespace detail 307 308 template <typename genFIType> 309 GLM_FUNC_QUALIFIER genFIType abs(genFIType x) 310 { 311 return detail::compute_abs<genFIType, std::numeric_limits<genFIType>::is_signed>::call(x); 312 } 313 314 template <typename T, precision P, template <typename, precision> class vecType> 315 GLM_FUNC_QUALIFIER vecType<T, P> abs(vecType<T, P> const & x) 316 { 317 return detail::compute_abs_vector<T, P, vecType, detail::is_aligned<P>::value>::call(x); 318 } 319 320 // sign 321 // fast and works for any type 322 template <typename genFIType> 323 GLM_FUNC_QUALIFIER genFIType sign(genFIType x) 324 { 325 GLM_STATIC_ASSERT( 326 std::numeric_limits<genFIType>::is_iec559 || (std::numeric_limits<genFIType>::is_signed && std::numeric_limits<genFIType>::is_integer), 327 "'sign' only accept signed inputs"); 328 329 return detail::compute_sign<genFIType, defaultp, tvec1, std::numeric_limits<genFIType>::is_iec559, highp>::call(tvec1<genFIType>(x)).x; 330 } 331 332 template <typename T, precision P, template <typename, precision> class vecType> 333 GLM_FUNC_QUALIFIER vecType<T, P> sign(vecType<T, P> const & x) 334 { 335 GLM_STATIC_ASSERT( 336 std::numeric_limits<T>::is_iec559 || (std::numeric_limits<T>::is_signed && std::numeric_limits<T>::is_integer), 337 "'sign' only accept signed inputs"); 338 339 return detail::compute_sign<T, P, vecType, std::numeric_limits<T>::is_iec559, detail::is_aligned<P>::value>::call(x); 340 } 341 342 // floor 343 using ::std::floor; 344 template <typename T, precision P, template <typename, precision> class vecType> 345 GLM_FUNC_QUALIFIER vecType<T, P> floor(vecType<T, P> const & x) 346 { 347 GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'floor' only accept floating-point inputs."); 348 return detail::compute_floor<T, P, vecType, detail::is_aligned<P>::value>::call(x); 349 } 350 351 template <typename T, precision P, template <typename, precision> class vecType> 352 GLM_FUNC_QUALIFIER vecType<T, P> trunc(vecType<T, P> const & x) 353 { 354 GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'trunc' only accept floating-point inputs"); 355 return detail::compute_trunc<T, P, vecType, detail::is_aligned<P>::value>::call(x); 356 } 357 358 template <typename T, precision P, template <typename, precision> class vecType> 359 GLM_FUNC_QUALIFIER vecType<T, P> round(vecType<T, P> const & x) 360 { 361 GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'round' only accept floating-point inputs"); 362 return detail::compute_round<T, P, vecType, detail::is_aligned<P>::value>::call(x); 363 } 364 365/* 366 // roundEven 367 template <typename genType> 368 GLM_FUNC_QUALIFIER genType roundEven(genType const& x) 369 { 370 GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'roundEven' only accept floating-point inputs"); 371 372 return genType(int(x + genType(int(x) % 2))); 373 } 374*/ 375 376 // roundEven 377 template <typename genType> 378 GLM_FUNC_QUALIFIER genType roundEven(genType x) 379 { 380 GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'roundEven' only accept floating-point inputs"); 381 382 int Integer = static_cast<int>(x); 383 genType IntegerPart = static_cast<genType>(Integer); 384 genType FractionalPart = fract(x); 385 386 if(FractionalPart > static_cast<genType>(0.5) || FractionalPart < static_cast<genType>(0.5)) 387 { 388 return round(x); 389 } 390 else if((Integer % 2) == 0) 391 { 392 return IntegerPart; 393 } 394 else if(x <= static_cast<genType>(0)) // Work around... 395 { 396 return IntegerPart - static_cast<genType>(1); 397 } 398 else 399 { 400 return IntegerPart + static_cast<genType>(1); 401 } 402 //else // Bug on MinGW 4.5.2 403 //{ 404 // return mix(IntegerPart + genType(-1), IntegerPart + genType(1), x <= genType(0)); 405 //} 406 } 407 408 template <typename T, precision P, template <typename, precision> class vecType> 409 GLM_FUNC_QUALIFIER vecType<T, P> roundEven(vecType<T, P> const & x) 410 { 411 GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'roundEven' only accept floating-point inputs"); 412 return detail::functor1<T, T, P, vecType>::call(roundEven, x); 413 } 414 415 // ceil 416 using ::std::ceil; 417 template <typename T, precision P, template <typename, precision> class vecType> 418 GLM_FUNC_QUALIFIER vecType<T, P> ceil(vecType<T, P> const & x) 419 { 420 GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'ceil' only accept floating-point inputs"); 421 return detail::compute_ceil<T, P, vecType, detail::is_aligned<P>::value>::call(x); 422 } 423 424 // fract 425 template <typename genType> 426 GLM_FUNC_QUALIFIER genType fract(genType x) 427 { 428 return fract(tvec1<genType>(x)).x; 429 } 430 431 template <typename T, precision P, template <typename, precision> class vecType> 432 GLM_FUNC_QUALIFIER vecType<T, P> fract(vecType<T, P> const & x) 433 { 434 GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'fract' only accept floating-point inputs"); 435 return detail::compute_fract<T, P, vecType, detail::is_aligned<P>::value>::call(x); 436 } 437 438 // mod 439 template <typename genType> 440 GLM_FUNC_QUALIFIER genType mod(genType x, genType y) 441 { 442# if GLM_COMPILER & GLM_COMPILER_CUDA 443 // Another Cuda compiler bug https://github.com/g-truc/glm/issues/530 444 tvec1<genType, defaultp> Result(mod(tvec1<genType, defaultp>(x), y)); 445 return Result.x; 446# else 447 return mod(tvec1<genType, defaultp>(x), y).x; 448# endif 449 } 450 451 template <typename T, precision P, template <typename, precision> class vecType> 452 GLM_FUNC_QUALIFIER vecType<T, P> mod(vecType<T, P> const & x, T y) 453 { 454 return detail::compute_mod<T, P, vecType, detail::is_aligned<P>::value>::call(x, vecType<T, P>(y)); 455 } 456 457 template <typename T, precision P, template <typename, precision> class vecType> 458 GLM_FUNC_QUALIFIER vecType<T, P> mod(vecType<T, P> const & x, vecType<T, P> const & y) 459 { 460 return detail::compute_mod<T, P, vecType, detail::is_aligned<P>::value>::call(x, y); 461 } 462 463 // modf 464 template <typename genType> 465 GLM_FUNC_QUALIFIER genType modf(genType x, genType & i) 466 { 467 GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'modf' only accept floating-point inputs"); 468 return std::modf(x, &i); 469 } 470 471 template <typename T, precision P> 472 GLM_FUNC_QUALIFIER tvec1<T, P> modf(tvec1<T, P> const & x, tvec1<T, P> & i) 473 { 474 return tvec1<T, P>( 475 modf(x.x, i.x)); 476 } 477 478 template <typename T, precision P> 479 GLM_FUNC_QUALIFIER tvec2<T, P> modf(tvec2<T, P> const & x, tvec2<T, P> & i) 480 { 481 return tvec2<T, P>( 482 modf(x.x, i.x), 483 modf(x.y, i.y)); 484 } 485 486 template <typename T, precision P> 487 GLM_FUNC_QUALIFIER tvec3<T, P> modf(tvec3<T, P> const & x, tvec3<T, P> & i) 488 { 489 return tvec3<T, P>( 490 modf(x.x, i.x), 491 modf(x.y, i.y), 492 modf(x.z, i.z)); 493 } 494 495 template <typename T, precision P> 496 GLM_FUNC_QUALIFIER tvec4<T, P> modf(tvec4<T, P> const & x, tvec4<T, P> & i) 497 { 498 return tvec4<T, P>( 499 modf(x.x, i.x), 500 modf(x.y, i.y), 501 modf(x.z, i.z), 502 modf(x.w, i.w)); 503 } 504 505 //// Only valid if (INT_MIN <= x-y <= INT_MAX) 506 //// min(x,y) 507 //r = y + ((x - y) & ((x - y) >> (sizeof(int) * 508 //CHAR_BIT - 1))); 509 //// max(x,y) 510 //r = x - ((x - y) & ((x - y) >> (sizeof(int) * 511 //CHAR_BIT - 1))); 512 513 // min 514 template <typename T, precision P, template <typename, precision> class vecType> 515 GLM_FUNC_QUALIFIER vecType<T, P> min(vecType<T, P> const & a, T b) 516 { 517 GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559 || GLM_UNRESTRICTED_GENTYPE, "'min' only accept floating-point inputs for the interpolator a"); 518 return detail::compute_min_vector<T, P, vecType, detail::is_aligned<P>::value>::call(a, vecType<T, P>(b)); 519 } 520 521 template <typename T, precision P, template <typename, precision> class vecType> 522 GLM_FUNC_QUALIFIER vecType<T, P> min(vecType<T, P> const & a, vecType<T, P> const & b) 523 { 524 return detail::compute_min_vector<T, P, vecType, detail::is_aligned<P>::value>::call(a, b); 525 } 526 527 // max 528 template <typename T, precision P, template <typename, precision> class vecType> 529 GLM_FUNC_QUALIFIER vecType<T, P> max(vecType<T, P> const & a, T b) 530 { 531 GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559 || GLM_UNRESTRICTED_GENTYPE, "'max' only accept floating-point inputs for the interpolator a"); 532 return detail::compute_max_vector<T, P, vecType, detail::is_aligned<P>::value>::call(a, vecType<T, P>(b)); 533 } 534 535 template <typename T, precision P, template <typename, precision> class vecType> 536 GLM_FUNC_QUALIFIER vecType<T, P> max(vecType<T, P> const & a, vecType<T, P> const & b) 537 { 538 return detail::compute_max_vector<T, P, vecType, detail::is_aligned<P>::value>::call(a, b); 539 } 540 541 // clamp 542 template <typename genType> 543 GLM_FUNC_QUALIFIER genType clamp(genType x, genType minVal, genType maxVal) 544 { 545 GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559 || std::numeric_limits<genType>::is_integer || GLM_UNRESTRICTED_GENTYPE, "'clamp' only accept floating-point or integer inputs"); 546 return min(max(x, minVal), maxVal); 547 } 548 549 template <typename T, precision P, template <typename, precision> class vecType> 550 GLM_FUNC_QUALIFIER vecType<T, P> clamp(vecType<T, P> const & x, T minVal, T maxVal) 551 { 552 GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559 || std::numeric_limits<T>::is_integer || GLM_UNRESTRICTED_GENTYPE, "'clamp' only accept floating-point or integer inputs"); 553 return detail::compute_clamp_vector<T, P, vecType, detail::is_aligned<P>::value>::call(x, vecType<T, P>(minVal), vecType<T, P>(maxVal)); 554 } 555 556 template <typename T, precision P, template <typename, precision> class vecType> 557 GLM_FUNC_QUALIFIER vecType<T, P> clamp(vecType<T, P> const & x, vecType<T, P> const & minVal, vecType<T, P> const & maxVal) 558 { 559 GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559 || std::numeric_limits<T>::is_integer || GLM_UNRESTRICTED_GENTYPE, "'clamp' only accept floating-point or integer inputs"); 560 return detail::compute_clamp_vector<T, P, vecType, detail::is_aligned<P>::value>::call(x, minVal, maxVal); 561 } 562 563 template <typename genTypeT, typename genTypeU> 564 GLM_FUNC_QUALIFIER genTypeT mix(genTypeT x, genTypeT y, genTypeU a) 565 { 566 return detail::compute_mix<genTypeT, genTypeU>::call(x, y, a); 567 } 568 569 template <typename T, typename U, precision P, template <typename, precision> class vecType> 570 GLM_FUNC_QUALIFIER vecType<T, P> mix(vecType<T, P> const & x, vecType<T, P> const & y, U a) 571 { 572 return detail::compute_mix_scalar<T, U, P, vecType, detail::is_aligned<P>::value>::call(x, y, a); 573 } 574 575 template <typename T, typename U, precision P, template <typename, precision> class vecType> 576 GLM_FUNC_QUALIFIER vecType<T, P> mix(vecType<T, P> const & x, vecType<T, P> const & y, vecType<U, P> const & a) 577 { 578 return detail::compute_mix_vector<T, U, P, vecType, detail::is_aligned<P>::value>::call(x, y, a); 579 } 580 581 // step 582 template <typename genType> 583 GLM_FUNC_QUALIFIER genType step(genType edge, genType x) 584 { 585 return mix(static_cast<genType>(1), static_cast<genType>(0), glm::lessThan(x, edge)); 586 } 587 588 template <template <typename, precision> class vecType, typename T, precision P> 589 GLM_FUNC_QUALIFIER vecType<T, P> step(T edge, vecType<T, P> const & x) 590 { 591 return detail::compute_step_vector<T, P, vecType, detail::is_aligned<P>::value>::call(vecType<T, P>(edge), x); 592 } 593 594 template <template <typename, precision> class vecType, typename T, precision P> 595 GLM_FUNC_QUALIFIER vecType<T, P> step(vecType<T, P> const & edge, vecType<T, P> const & x) 596 { 597 return detail::compute_step_vector<T, P, vecType, detail::is_aligned<P>::value>::call(edge, x); 598 } 599 600 // smoothstep 601 template <typename genType> 602 GLM_FUNC_QUALIFIER genType smoothstep(genType edge0, genType edge1, genType x) 603 { 604 GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559 || GLM_UNRESTRICTED_GENTYPE, "'smoothstep' only accept floating-point inputs"); 605 606 genType const tmp(clamp((x - edge0) / (edge1 - edge0), genType(0), genType(1))); 607 return tmp * tmp * (genType(3) - genType(2) * tmp); 608 } 609 610 template <typename T, precision P, template <typename, precision> class vecType> 611 GLM_FUNC_QUALIFIER vecType<T, P> smoothstep(T edge0, T edge1, vecType<T, P> const & x) 612 { 613 return detail::compute_smoothstep_vector<T, P, vecType, detail::is_aligned<P>::value>::call(vecType<T, P>(edge0), vecType<T, P>(edge1), x); 614 } 615 616 template <typename T, precision P, template <typename, precision> class vecType> 617 GLM_FUNC_QUALIFIER vecType<T, P> smoothstep(vecType<T, P> const & edge0, vecType<T, P> const & edge1, vecType<T, P> const & x) 618 { 619 return detail::compute_smoothstep_vector<T, P, vecType, detail::is_aligned<P>::value>::call(edge0, edge1, x); 620 } 621 622# if GLM_HAS_CXX11_STL 623 using std::isnan; 624# else 625 template <typename genType> 626 GLM_FUNC_QUALIFIER bool isnan(genType x) 627 { 628 GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'isnan' only accept floating-point inputs"); 629 630# if GLM_HAS_CXX11_STL 631 return std::isnan(x); 632# elif GLM_COMPILER & GLM_COMPILER_VC 633 return _isnan(x) != 0; 634# elif GLM_COMPILER & GLM_COMPILER_INTEL 635# if GLM_PLATFORM & GLM_PLATFORM_WINDOWS 636 return _isnan(x) != 0; 637# else 638 return ::isnan(x) != 0; 639# endif 640# elif (GLM_COMPILER & (GLM_COMPILER_GCC | GLM_COMPILER_CLANG)) && (GLM_PLATFORM & GLM_PLATFORM_ANDROID) && __cplusplus < 201103L 641 return _isnan(x) != 0; 642# elif GLM_COMPILER & GLM_COMPILER_CUDA 643 return isnan(x) != 0; 644# else 645 return std::isnan(x); 646# endif 647 } 648# endif 649 650 template <typename T, precision P, template <typename, precision> class vecType> 651 GLM_FUNC_QUALIFIER vecType<bool, P> isnan(vecType<T, P> const & x) 652 { 653 GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'isnan' only accept floating-point inputs"); 654 655 return detail::functor1<bool, T, P, vecType>::call(isnan, x); 656 } 657 658# if GLM_HAS_CXX11_STL 659 using std::isinf; 660# else 661 template <typename genType> 662 GLM_FUNC_QUALIFIER bool isinf(genType x) 663 { 664 GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'isinf' only accept floating-point inputs"); 665 666# if GLM_HAS_CXX11_STL 667 return std::isinf(x); 668# elif GLM_COMPILER & (GLM_COMPILER_INTEL | GLM_COMPILER_VC) 669# if(GLM_PLATFORM & GLM_PLATFORM_WINDOWS) 670 return _fpclass(x) == _FPCLASS_NINF || _fpclass(x) == _FPCLASS_PINF; 671# else 672 return ::isinf(x); 673# endif 674# elif GLM_COMPILER & (GLM_COMPILER_GCC | GLM_COMPILER_CLANG) 675# if(GLM_PLATFORM & GLM_PLATFORM_ANDROID && __cplusplus < 201103L) 676 return _isinf(x) != 0; 677# else 678 return std::isinf(x); 679# endif 680# elif GLM_COMPILER & GLM_COMPILER_CUDA 681 // http://developer.download.nvidia.com/compute/cuda/4_2/rel/toolkit/docs/online/group__CUDA__MATH__DOUBLE_g13431dd2b40b51f9139cbb7f50c18fab.html#g13431dd2b40b51f9139cbb7f50c18fab 682 return isinf(double(x)) != 0; 683# else 684 return std::isinf(x); 685# endif 686 } 687# endif 688 689 template <typename T, precision P, template <typename, precision> class vecType> 690 GLM_FUNC_QUALIFIER vecType<bool, P> isinf(vecType<T, P> const & x) 691 { 692 GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'isnan' only accept floating-point inputs"); 693 694 return detail::functor1<bool, T, P, vecType>::call(isinf, x); 695 } 696 697 GLM_FUNC_QUALIFIER int floatBitsToInt(float const & v) 698 { 699 return reinterpret_cast<int&>(const_cast<float&>(v)); 700 } 701 702 template <template <typename, precision> class vecType, precision P> 703 GLM_FUNC_QUALIFIER vecType<int, P> floatBitsToInt(vecType<float, P> const & v) 704 { 705 return reinterpret_cast<vecType<int, P>&>(const_cast<vecType<float, P>&>(v)); 706 } 707 708 GLM_FUNC_QUALIFIER uint floatBitsToUint(float const & v) 709 { 710 return reinterpret_cast<uint&>(const_cast<float&>(v)); 711 } 712 713 template <template <typename, precision> class vecType, precision P> 714 GLM_FUNC_QUALIFIER vecType<uint, P> floatBitsToUint(vecType<float, P> const & v) 715 { 716 return reinterpret_cast<vecType<uint, P>&>(const_cast<vecType<float, P>&>(v)); 717 } 718 719 GLM_FUNC_QUALIFIER float intBitsToFloat(int const & v) 720 { 721 return reinterpret_cast<float&>(const_cast<int&>(v)); 722 } 723 724 template <template <typename, precision> class vecType, precision P> 725 GLM_FUNC_QUALIFIER vecType<float, P> intBitsToFloat(vecType<int, P> const & v) 726 { 727 return reinterpret_cast<vecType<float, P>&>(const_cast<vecType<int, P>&>(v)); 728 } 729 730 GLM_FUNC_QUALIFIER float uintBitsToFloat(uint const & v) 731 { 732 return reinterpret_cast<float&>(const_cast<uint&>(v)); 733 } 734 735 template <template <typename, precision> class vecType, precision P> 736 GLM_FUNC_QUALIFIER vecType<float, P> uintBitsToFloat(vecType<uint, P> const & v) 737 { 738 return reinterpret_cast<vecType<float, P>&>(const_cast<vecType<uint, P>&>(v)); 739 } 740 741 template <typename genType> 742 GLM_FUNC_QUALIFIER genType fma(genType const & a, genType const & b, genType const & c) 743 { 744 return a * b + c; 745 } 746 747 template <typename genType> 748 GLM_FUNC_QUALIFIER genType frexp(genType x, int & exp) 749 { 750 GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559 || GLM_UNRESTRICTED_GENTYPE, "'frexp' only accept floating-point inputs"); 751 752 return std::frexp(x, &exp); 753 } 754 755 template <typename T, precision P> 756 GLM_FUNC_QUALIFIER tvec1<T, P> frexp(tvec1<T, P> const & x, tvec1<int, P> & exp) 757 { 758 GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559 || GLM_UNRESTRICTED_GENTYPE, "'frexp' only accept floating-point inputs"); 759 760 return tvec1<T, P>(std::frexp(x.x, &exp.x)); 761 } 762 763 template <typename T, precision P> 764 GLM_FUNC_QUALIFIER tvec2<T, P> frexp(tvec2<T, P> const & x, tvec2<int, P> & exp) 765 { 766 GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559 || GLM_UNRESTRICTED_GENTYPE, "'frexp' only accept floating-point inputs"); 767 768 return tvec2<T, P>( 769 frexp(x.x, exp.x), 770 frexp(x.y, exp.y)); 771 } 772 773 template <typename T, precision P> 774 GLM_FUNC_QUALIFIER tvec3<T, P> frexp(tvec3<T, P> const & x, tvec3<int, P> & exp) 775 { 776 GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559 || GLM_UNRESTRICTED_GENTYPE, "'frexp' only accept floating-point inputs"); 777 778 return tvec3<T, P>( 779 frexp(x.x, exp.x), 780 frexp(x.y, exp.y), 781 frexp(x.z, exp.z)); 782 } 783 784 template <typename T, precision P> 785 GLM_FUNC_QUALIFIER tvec4<T, P> frexp(tvec4<T, P> const & x, tvec4<int, P> & exp) 786 { 787 GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559 || GLM_UNRESTRICTED_GENTYPE, "'frexp' only accept floating-point inputs"); 788 789 return tvec4<T, P>( 790 frexp(x.x, exp.x), 791 frexp(x.y, exp.y), 792 frexp(x.z, exp.z), 793 frexp(x.w, exp.w)); 794 } 795 796 template <typename genType> 797 GLM_FUNC_QUALIFIER genType ldexp(genType const & x, int const & exp) 798 { 799 GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559 || GLM_UNRESTRICTED_GENTYPE, "'ldexp' only accept floating-point inputs"); 800 801 return std::ldexp(x, exp); 802 } 803 804 template <typename T, precision P> 805 GLM_FUNC_QUALIFIER tvec1<T, P> ldexp(tvec1<T, P> const & x, tvec1<int, P> const & exp) 806 { 807 GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559 || GLM_UNRESTRICTED_GENTYPE, "'ldexp' only accept floating-point inputs"); 808 809 return tvec1<T, P>( 810 ldexp(x.x, exp.x)); 811 } 812 813 template <typename T, precision P> 814 GLM_FUNC_QUALIFIER tvec2<T, P> ldexp(tvec2<T, P> const & x, tvec2<int, P> const & exp) 815 { 816 GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559 || GLM_UNRESTRICTED_GENTYPE, "'ldexp' only accept floating-point inputs"); 817 818 return tvec2<T, P>( 819 ldexp(x.x, exp.x), 820 ldexp(x.y, exp.y)); 821 } 822 823 template <typename T, precision P> 824 GLM_FUNC_QUALIFIER tvec3<T, P> ldexp(tvec3<T, P> const & x, tvec3<int, P> const & exp) 825 { 826 GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559 || GLM_UNRESTRICTED_GENTYPE, "'ldexp' only accept floating-point inputs"); 827 828 return tvec3<T, P>( 829 ldexp(x.x, exp.x), 830 ldexp(x.y, exp.y), 831 ldexp(x.z, exp.z)); 832 } 833 834 template <typename T, precision P> 835 GLM_FUNC_QUALIFIER tvec4<T, P> ldexp(tvec4<T, P> const & x, tvec4<int, P> const & exp) 836 { 837 GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559 || GLM_UNRESTRICTED_GENTYPE, "'ldexp' only accept floating-point inputs"); 838 839 return tvec4<T, P>( 840 ldexp(x.x, exp.x), 841 ldexp(x.y, exp.y), 842 ldexp(x.z, exp.z), 843 ldexp(x.w, exp.w)); 844 } 845}//namespace glm 846 847#if GLM_ARCH != GLM_ARCH_PURE && GLM_HAS_UNRESTRICTED_UNIONS 848# include "func_common_simd.inl" 849#endif 850