You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

648 lines
16 KiB

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