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