Home | History | Annotate | Download | only in detail
      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 
     36 namespace glm{
     37 namespace 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