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_integer.inl
     25 /// @date 2010-03-17 / 2011-06-15
     26 /// @author Christophe Riccio
     27 ///////////////////////////////////////////////////////////////////////////////////
     28 
     29 #include "type_vec2.hpp"
     30 #include "type_vec3.hpp"
     31 #include "type_vec4.hpp"
     32 #include "type_int.hpp"
     33 #include "_vectorize.hpp"
     34 #if(GLM_ARCH != GLM_ARCH_PURE)
     35 #if(GLM_COMPILER & GLM_COMPILER_VC)
     36 #	include <intrin.h>
     37 #	pragma intrinsic(_BitScanReverse)
     38 #endif//(GLM_COMPILER & GLM_COMPILER_VC)
     39 #endif//(GLM_ARCH != GLM_ARCH_PURE)
     40 #include <limits>
     41 
     42 namespace glm
     43 {
     44 	// uaddCarry
     45 	template <>
     46 	GLM_FUNC_QUALIFIER uint uaddCarry
     47 	(
     48 		uint const & x,
     49 		uint const & y,
     50 		uint & Carry
     51 	)
     52 	{
     53 		uint64 Value64 = static_cast<uint64>(x) + static_cast<uint64>(y);
     54 		uint32 Result = static_cast<uint32>(Value64 % (static_cast<uint64>(1) << static_cast<uint64>(32)));
     55 		Carry = (Value64 % (static_cast<uint64>(1) << static_cast<uint64>(32))) > 1 ? static_cast<uint32>(1) : static_cast<uint32>(0);
     56 		return Result;
     57 	}
     58 
     59 	template <>
     60 	GLM_FUNC_QUALIFIER uvec2 uaddCarry
     61 	(
     62 		uvec2 const & x,
     63 		uvec2 const & y,
     64 		uvec2 & Carry
     65 	)
     66 	{
     67 		return uvec2(
     68 			uaddCarry(x[0], y[0], Carry[0]),
     69 			uaddCarry(x[1], y[1], Carry[1]));
     70 	}
     71 
     72 	template <>
     73 	GLM_FUNC_QUALIFIER uvec3 uaddCarry
     74 	(
     75 		uvec3 const & x,
     76 		uvec3 const & y,
     77 		uvec3 & Carry
     78 	)
     79 	{
     80 		return uvec3(
     81 			uaddCarry(x[0], y[0], Carry[0]),
     82 			uaddCarry(x[1], y[1], Carry[1]),
     83 			uaddCarry(x[2], y[2], Carry[2]));
     84 	}
     85 
     86 	template <>
     87 	GLM_FUNC_QUALIFIER uvec4 uaddCarry
     88 	(
     89 		uvec4 const & x,
     90 		uvec4 const & y,
     91 		uvec4 & Carry
     92 	)
     93 	{
     94 		return uvec4(
     95 			uaddCarry(x[0], y[0], Carry[0]),
     96 			uaddCarry(x[1], y[1], Carry[1]),
     97 			uaddCarry(x[2], y[2], Carry[2]),
     98 			uaddCarry(x[3], y[3], Carry[3]));
     99 	}
    100 
    101 	// usubBorrow
    102 	template <>
    103 	GLM_FUNC_QUALIFIER uint usubBorrow
    104 	(
    105 		uint const & x,
    106 		uint const & y,
    107 		uint & Borrow
    108 	)
    109 	{
    110 		GLM_STATIC_ASSERT(sizeof(uint) == sizeof(uint32), "uint and uint32 size mismatch");
    111 
    112 		Borrow = x >= y ? static_cast<uint32>(0) : static_cast<uint32>(1);
    113 		if(y >= x)
    114 			return y - x;
    115 		else
    116 			return static_cast<uint32>((static_cast<int64>(1) << static_cast<int64>(32)) + (static_cast<int64>(y) - static_cast<int64>(x)));
    117 	}
    118 
    119 	template <>
    120 	GLM_FUNC_QUALIFIER uvec2 usubBorrow
    121 	(
    122 		uvec2 const & x,
    123 		uvec2 const & y,
    124 		uvec2 & Borrow
    125 	)
    126 	{
    127 		return uvec2(
    128 			usubBorrow(x[0], y[0], Borrow[0]),
    129 			usubBorrow(x[1], y[1], Borrow[1]));
    130 	}
    131 
    132 	template <>
    133 	GLM_FUNC_QUALIFIER uvec3 usubBorrow
    134 	(
    135 		uvec3 const & x,
    136 		uvec3 const & y,
    137 		uvec3 & Borrow
    138 	)
    139 	{
    140 		return uvec3(
    141 			usubBorrow(x[0], y[0], Borrow[0]),
    142 			usubBorrow(x[1], y[1], Borrow[1]),
    143 			usubBorrow(x[2], y[2], Borrow[2]));
    144 	}
    145 
    146 	template <>
    147 	GLM_FUNC_QUALIFIER uvec4 usubBorrow
    148 	(
    149 		uvec4 const & x,
    150 		uvec4 const & y,
    151 		uvec4 & Borrow
    152 	)
    153 	{
    154 		return uvec4(
    155 			usubBorrow(x[0], y[0], Borrow[0]),
    156 			usubBorrow(x[1], y[1], Borrow[1]),
    157 			usubBorrow(x[2], y[2], Borrow[2]),
    158 			usubBorrow(x[3], y[3], Borrow[3]));
    159 	}
    160 
    161 	// umulExtended
    162 	template <>
    163 	GLM_FUNC_QUALIFIER void umulExtended
    164 	(
    165 		uint const & x,
    166 		uint const & y,
    167 		uint & msb,
    168 		uint & lsb
    169 	)
    170 	{
    171 		GLM_STATIC_ASSERT(sizeof(uint) == sizeof(uint32), "uint and uint32 size mismatch");
    172 
    173 		uint64 Value64 = static_cast<uint64>(x) * static_cast<uint64>(y);
    174 		uint32* PointerMSB = (reinterpret_cast<uint32*>(&Value64) + 1);
    175 		msb = *PointerMSB;
    176 		uint32* PointerLSB = (reinterpret_cast<uint32*>(&Value64) + 0);
    177 		lsb = *PointerLSB;
    178 	}
    179 
    180 	template <>
    181 	GLM_FUNC_QUALIFIER void umulExtended
    182 	(
    183 		uvec2 const & x,
    184 		uvec2 const & y,
    185 		uvec2 & msb,
    186 		uvec2 & lsb
    187 	)
    188 	{
    189 		umulExtended(x[0], y[0], msb[0], lsb[0]);
    190 		umulExtended(x[1], y[1], msb[1], lsb[1]);
    191 	}
    192 
    193 	template <>
    194 	GLM_FUNC_QUALIFIER void umulExtended
    195 	(
    196 		uvec3 const & x,
    197 		uvec3 const & y,
    198 		uvec3 & msb,
    199 		uvec3 & lsb
    200 	)
    201 	{
    202 		umulExtended(x[0], y[0], msb[0], lsb[0]);
    203 		umulExtended(x[1], y[1], msb[1], lsb[1]);
    204 		umulExtended(x[2], y[2], msb[2], lsb[2]);
    205 	}
    206 
    207 	template <>
    208 	GLM_FUNC_QUALIFIER void umulExtended
    209 	(
    210 		uvec4 const & x,
    211 		uvec4 const & y,
    212 		uvec4 & msb,
    213 		uvec4 & lsb
    214 	)
    215 	{
    216 		umulExtended(x[0], y[0], msb[0], lsb[0]);
    217 		umulExtended(x[1], y[1], msb[1], lsb[1]);
    218 		umulExtended(x[2], y[2], msb[2], lsb[2]);
    219 		umulExtended(x[3], y[3], msb[3], lsb[3]);
    220 	}
    221 
    222 	// imulExtended
    223 	template <>
    224 	GLM_FUNC_QUALIFIER void imulExtended
    225 	(
    226 		int const & x,
    227 		int const & y,
    228 		int & msb,
    229 		int & lsb
    230 	)
    231 	{
    232 		GLM_STATIC_ASSERT(sizeof(int) == sizeof(int32), "int and int32 size mismatch");
    233 
    234 		int64 Value64 = static_cast<int64>(x) * static_cast<int64>(y);
    235 		int32* PointerMSB = (reinterpret_cast<int32*>(&Value64) + 1);
    236 		msb = *PointerMSB;
    237 		int32* PointerLSB = (reinterpret_cast<int32*>(&Value64));
    238 		lsb = *PointerLSB;
    239 	}
    240 
    241 	template <>
    242 	GLM_FUNC_QUALIFIER void imulExtended
    243 	(
    244 		ivec2 const & x,
    245 		ivec2 const & y,
    246 		ivec2 & msb,
    247 		ivec2 & lsb
    248 	)
    249 	{
    250 		imulExtended(x[0], y[0], msb[0], lsb[0]),
    251 		imulExtended(x[1], y[1], msb[1], lsb[1]);
    252 	}
    253 
    254 	template <>
    255 	GLM_FUNC_QUALIFIER void imulExtended
    256 	(
    257 		ivec3 const & x,
    258 		ivec3 const & y,
    259 		ivec3 & msb,
    260 		ivec3 & lsb
    261 	)
    262 	{
    263 		imulExtended(x[0], y[0], msb[0], lsb[0]),
    264 		imulExtended(x[1], y[1], msb[1], lsb[1]);
    265 		imulExtended(x[2], y[2], msb[2], lsb[2]);
    266 	}
    267 
    268 	template <>
    269 	GLM_FUNC_QUALIFIER void imulExtended
    270 	(
    271 		ivec4 const & x,
    272 		ivec4 const & y,
    273 		ivec4 & msb,
    274 		ivec4 & lsb
    275 	)
    276 	{
    277 		imulExtended(x[0], y[0], msb[0], lsb[0]),
    278 		imulExtended(x[1], y[1], msb[1], lsb[1]);
    279 		imulExtended(x[2], y[2], msb[2], lsb[2]);
    280 		imulExtended(x[3], y[3], msb[3], lsb[3]);
    281 	}
    282 
    283 	// bitfieldExtract
    284 	template <typename genIUType>
    285 	GLM_FUNC_QUALIFIER genIUType bitfieldExtract
    286 	(
    287 		genIUType const & Value,
    288 		int const & Offset,
    289 		int const & Bits
    290 	)
    291 	{
    292 		int GenSize = int(sizeof(genIUType)) << int(3);
    293 
    294 		assert(Offset + Bits <= GenSize);
    295 
    296 		genIUType ShiftLeft = Bits ? Value << (GenSize - (Bits + Offset)) : genIUType(0);
    297 		genIUType ShiftBack = ShiftLeft >> genIUType(GenSize - Bits);
    298 
    299 		return ShiftBack;
    300 	}
    301 
    302 	template <typename T, precision P>
    303 	GLM_FUNC_QUALIFIER detail::tvec2<T, P> bitfieldExtract
    304 	(
    305 		detail::tvec2<T, P> const & Value,
    306 		int const & Offset,
    307 		int const & Bits
    308 	)
    309 	{
    310 		return detail::tvec2<T, P>(
    311 			bitfieldExtract(Value[0], Offset, Bits),
    312 			bitfieldExtract(Value[1], Offset, Bits));
    313 	}
    314 
    315 	template <typename T, precision P>
    316 	GLM_FUNC_QUALIFIER detail::tvec3<T, P> bitfieldExtract
    317 	(
    318 		detail::tvec3<T, P> const & Value,
    319 		int const & Offset,
    320 		int const & Bits
    321 	)
    322 	{
    323 		return detail::tvec3<T, P>(
    324 			bitfieldExtract(Value[0], Offset, Bits),
    325 			bitfieldExtract(Value[1], Offset, Bits),
    326 			bitfieldExtract(Value[2], Offset, Bits));
    327 	}
    328 
    329 	template <typename T, precision P>
    330 	GLM_FUNC_QUALIFIER detail::tvec4<T, P> bitfieldExtract
    331 	(
    332 		detail::tvec4<T, P> const & Value,
    333 		int const & Offset,
    334 		int const & Bits
    335 	)
    336 	{
    337 		return detail::tvec4<T, P>(
    338 			bitfieldExtract(Value[0], Offset, Bits),
    339 			bitfieldExtract(Value[1], Offset, Bits),
    340 			bitfieldExtract(Value[2], Offset, Bits),
    341 			bitfieldExtract(Value[3], Offset, Bits));
    342 	}
    343 
    344 	// bitfieldInsert
    345 	template <typename genIUType>
    346 	GLM_FUNC_QUALIFIER genIUType bitfieldInsert
    347 	(
    348 		genIUType const & Base,
    349 		genIUType const & Insert,
    350 		int const & Offset,
    351 		int const & Bits
    352 	)
    353 	{
    354 		GLM_STATIC_ASSERT(std::numeric_limits<genIUType>::is_integer, "'bitfieldInsert' only accept integer values");
    355 		assert(Offset + Bits <= sizeof(genIUType));
    356 
    357 		if(Bits == 0)
    358 			return Base;
    359 
    360 		genIUType Mask = 0;
    361 		for(int Bit = Offset; Bit < Offset + Bits; ++Bit)
    362 			Mask |= (1 << Bit);
    363 
    364 		return (Base & ~Mask) | (Insert & Mask);
    365 	}
    366 
    367 	template <typename T, precision P>
    368 	GLM_FUNC_QUALIFIER detail::tvec2<T, P> bitfieldInsert
    369 	(
    370 		detail::tvec2<T, P> const & Base,
    371 		detail::tvec2<T, P> const & Insert,
    372 		int const & Offset,
    373 		int const & Bits
    374 	)
    375 	{
    376 		return detail::tvec2<T, P>(
    377 			bitfieldInsert(Base[0], Insert[0], Offset, Bits),
    378 			bitfieldInsert(Base[1], Insert[1], Offset, Bits));
    379 	}
    380 
    381 	template <typename T, precision P>
    382 	GLM_FUNC_QUALIFIER detail::tvec3<T, P> bitfieldInsert
    383 	(
    384 		detail::tvec3<T, P> const & Base,
    385 		detail::tvec3<T, P> const & Insert,
    386 		int const & Offset,
    387 		int const & Bits
    388 	)
    389 	{
    390 		return detail::tvec3<T, P>(
    391 			bitfieldInsert(Base[0], Insert[0], Offset, Bits),
    392 			bitfieldInsert(Base[1], Insert[1], Offset, Bits),
    393 			bitfieldInsert(Base[2], Insert[2], Offset, Bits));
    394 	}
    395 
    396 	template <typename T, precision P>
    397 	GLM_FUNC_QUALIFIER detail::tvec4<T, P> bitfieldInsert
    398 	(
    399 		detail::tvec4<T, P> const & Base,
    400 		detail::tvec4<T, P> const & Insert,
    401 		int const & Offset,
    402 		int const & Bits
    403 	)
    404 	{
    405 		return detail::tvec4<T, P>(
    406 			bitfieldInsert(Base[0], Insert[0], Offset, Bits),
    407 			bitfieldInsert(Base[1], Insert[1], Offset, Bits),
    408 			bitfieldInsert(Base[2], Insert[2], Offset, Bits),
    409 			bitfieldInsert(Base[3], Insert[3], Offset, Bits));
    410 	}
    411 
    412 	// bitfieldReverse
    413 	template <typename genIUType>
    414 	GLM_FUNC_QUALIFIER genIUType bitfieldReverse(genIUType const & Value)
    415 	{
    416 		GLM_STATIC_ASSERT(std::numeric_limits<genIUType>::is_integer, "'bitfieldReverse' only accept integer values");
    417 
    418 		genIUType Out = 0;
    419 		std::size_t BitSize = sizeof(genIUType) * 8;
    420 		for(std::size_t i = 0; i < BitSize; ++i)
    421 			if(Value & (genIUType(1) << i))
    422 				Out |= genIUType(1) << (BitSize - 1 - i);
    423 		return Out;
    424 	}	
    425 
    426 	VECTORIZE_VEC(bitfieldReverse)
    427 
    428 	// bitCount
    429 	template <typename genIUType>
    430 	GLM_FUNC_QUALIFIER int bitCount(genIUType const & Value)
    431 	{
    432 		GLM_STATIC_ASSERT(std::numeric_limits<genIUType>::is_integer, "'bitCount' only accept integer values");
    433 
    434 		int Count = 0;
    435 		for(std::size_t i = 0; i < sizeof(genIUType) * std::size_t(8); ++i)
    436 		{
    437 			if(Value & (1 << i))
    438 				++Count;
    439 		}
    440 		return Count;
    441 	}
    442 
    443 	template <typename T, precision P>
    444 	GLM_FUNC_QUALIFIER detail::tvec2<int, P> bitCount
    445 	(
    446 		detail::tvec2<T, P> const & value
    447 	)
    448 	{
    449 		return detail::tvec2<int, P>(
    450 			bitCount(value[0]),
    451 			bitCount(value[1]));
    452 	}
    453 
    454 	template <typename T, precision P>
    455 	GLM_FUNC_QUALIFIER detail::tvec3<int, P> bitCount
    456 	(
    457 		detail::tvec3<T, P> const & value
    458 	)
    459 	{
    460 		return detail::tvec3<int, P>(
    461 			bitCount(value[0]),
    462 			bitCount(value[1]),
    463 			bitCount(value[2]));
    464 	}
    465 
    466 	template <typename T, precision P>
    467 	GLM_FUNC_QUALIFIER detail::tvec4<int, P> bitCount
    468 	(
    469 		detail::tvec4<T, P> const & value
    470 	)
    471 	{
    472 		return detail::tvec4<int, P>(
    473 			bitCount(value[0]),
    474 			bitCount(value[1]),
    475 			bitCount(value[2]),
    476 			bitCount(value[3]));
    477 	}
    478 
    479 	// findLSB
    480 	template <typename genIUType>
    481 	GLM_FUNC_QUALIFIER int findLSB
    482 	(
    483 		genIUType const & Value
    484 	)
    485 	{
    486 		GLM_STATIC_ASSERT(std::numeric_limits<genIUType>::is_integer, "'findLSB' only accept integer values");
    487 		if(Value == 0)
    488 			return -1;
    489 
    490 		genIUType Bit;
    491 		for(Bit = genIUType(0); !(Value & (1 << Bit)); ++Bit){}
    492 		return Bit;
    493 	}
    494 
    495 	template <typename T, precision P>
    496 	GLM_FUNC_QUALIFIER detail::tvec2<int, P> findLSB
    497 	(
    498 		detail::tvec2<T, P> const & value
    499 	)
    500 	{
    501 		return detail::tvec2<int, P>(
    502 			findLSB(value[0]),
    503 			findLSB(value[1]));
    504 	}
    505 
    506 	template <typename T, precision P>
    507 	GLM_FUNC_QUALIFIER detail::tvec3<int, P> findLSB
    508 	(
    509 		detail::tvec3<T, P> const & value
    510 	)
    511 	{
    512 		return detail::tvec3<int, P>(
    513 			findLSB(value[0]),
    514 			findLSB(value[1]),
    515 			findLSB(value[2]));
    516 	}
    517 
    518 	template <typename T, precision P>
    519 	GLM_FUNC_QUALIFIER detail::tvec4<int, P> findLSB
    520 	(
    521 		detail::tvec4<T, P> const & value
    522 	)
    523 	{
    524 		return detail::tvec4<int, P>(
    525 			findLSB(value[0]),
    526 			findLSB(value[1]),
    527 			findLSB(value[2]),
    528 			findLSB(value[3]));
    529 	}
    530 
    531 	// findMSB
    532 #if((GLM_ARCH != GLM_ARCH_PURE) && (GLM_COMPILER & GLM_COMPILER_VC))
    533 
    534 	template <typename genIUType>
    535 	GLM_FUNC_QUALIFIER int findMSB
    536 	(
    537 		genIUType const & Value
    538 	)
    539 	{
    540 		GLM_STATIC_ASSERT(std::numeric_limits<genIUType>::is_integer, "'findMSB' only accept integer values");
    541 		if(Value == 0)
    542 			return -1;
    543 
    544 		unsigned long Result(0);
    545 		_BitScanReverse(&Result, Value);
    546 		return int(Result);
    547 	}
    548 /*
    549 // __builtin_clz seems to be buggy as it crasks for some values, from 0x00200000 to 80000000
    550 #elif((GLM_ARCH != GLM_ARCH_PURE) && (GLM_COMPILER & GLM_COMPILER_GCC) && (GLM_COMPILER >= GLM_COMPILER_GCC40))
    551 
    552 	template <typename genIUType>
    553 	GLM_FUNC_QUALIFIER int findMSB
    554 	(
    555 		genIUType const & Value
    556 	)
    557 	{
    558 		GLM_STATIC_ASSERT(std::numeric_limits<genIUType>::is_integer, "'findMSB' only accept integer values");
    559 		if(Value == 0)
    560 			return -1;
    561 
    562 		// clz returns the number or trailing 0-bits; see
    563 		// http://gcc.gnu.org/onlinedocs/gcc-4.7.1/gcc/Other-Builtins.html
    564 		//
    565 		// NoteBecause __builtin_clz only works for unsigned ints, this
    566 		// implementation will not work for 64-bit integers.
    567 		//
    568 		return 31 - __builtin_clzl(Value);
    569 	}
    570 */
    571 #else
    572 
    573 /* SSE implementation idea
    574 
    575 		__m128i const Zero = _mm_set_epi32( 0,  0,  0,  0);
    576 		__m128i const One = _mm_set_epi32( 1,  1,  1,  1);
    577 		__m128i Bit = _mm_set_epi32(-1, -1, -1, -1);
    578 		__m128i Tmp = _mm_set_epi32(Value, Value, Value, Value);
    579 		__m128i Mmi = Zero;
    580 		for(int i = 0; i < 32; ++i)
    581 		{
    582 			__m128i Shilt = _mm_and_si128(_mm_cmpgt_epi32(Tmp, One), One);
    583 			Tmp = _mm_srai_epi32(Tmp, One);
    584 			Bit = _mm_add_epi32(Bit, _mm_and_si128(Shilt, i));
    585 			Mmi = _mm_and_si128(Mmi, One);
    586 		}
    587 		return Bit;
    588 
    589 */
    590 
    591 	template <typename genIUType>
    592 	GLM_FUNC_QUALIFIER int findMSB
    593 	(
    594 		genIUType const & Value
    595 	)
    596 	{
    597 		GLM_STATIC_ASSERT(std::numeric_limits<genIUType>::is_integer, "'findMSB' only accept integer values");
    598 		
    599 		if(Value == genIUType(0) || Value == genIUType(-1))
    600 			return -1;
    601 		else if(Value > 0)
    602 		{
    603 			genIUType Bit = genIUType(-1);
    604 			for(genIUType tmp = Value; tmp > 0; tmp >>= 1, ++Bit){}
    605 			return Bit;
    606 		}
    607 		else //if(Value < 0)
    608 		{
    609 			int const BitCount(sizeof(genIUType) * 8);
    610 			int MostSignificantBit(-1);
    611 			for(int BitIndex(0); BitIndex < BitCount; ++BitIndex)
    612 				MostSignificantBit = (Value & (1 << BitIndex)) ? MostSignificantBit : BitIndex;
    613 			assert(MostSignificantBit >= 0);
    614 			return MostSignificantBit;
    615 		}
    616 	}
    617 #endif//(GLM_COMPILER)
    618 
    619 	template <typename T, precision P>
    620 	GLM_FUNC_QUALIFIER detail::tvec2<int, P> findMSB
    621 	(
    622 		detail::tvec2<T, P> const & value
    623 	)
    624 	{
    625 		return detail::tvec2<int, P>(
    626 			findMSB(value[0]),
    627 			findMSB(value[1]));
    628 	}
    629 
    630 	template <typename T, precision P>
    631 	GLM_FUNC_QUALIFIER detail::tvec3<int, P> findMSB
    632 	(
    633 		detail::tvec3<T, P> const & value
    634 	)
    635 	{
    636 		return detail::tvec3<int, P>(
    637 			findMSB(value[0]),
    638 			findMSB(value[1]),
    639 			findMSB(value[2]));
    640 	}
    641 
    642 	template <typename T, precision P>
    643 	GLM_FUNC_QUALIFIER detail::tvec4<int, P> findMSB
    644 	(
    645 		detail::tvec4<T, P> const & value
    646 	)
    647 	{
    648 		return detail::tvec4<int, P>(
    649 			findMSB(value[0]),
    650 			findMSB(value[1]),
    651 			findMSB(value[2]),
    652 			findMSB(value[3]));
    653 	}
    654 }//namespace glm
    655