blob: a788eb4cc84bfbaebbcd73cab86f0c0e4c75570c [file] [log] [blame]
Tony-LunarGb0b195d2015-05-13 15:01:06 -06001///////////////////////////////////////////////////////////////////////////////////
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