scalar_integer.inl 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. #include "../integer.hpp"
  2. namespace glm{
  3. namespace detail
  4. {
  5. template<length_t L, typename T, qualifier Q, bool compute = false>
  6. struct compute_ceilShift
  7. {
  8. GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& v, T)
  9. {
  10. return v;
  11. }
  12. };
  13. template<length_t L, typename T, qualifier Q>
  14. struct compute_ceilShift<L, T, Q, true>
  15. {
  16. GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& v, T Shift)
  17. {
  18. return v | (v >> Shift);
  19. }
  20. };
  21. template<length_t L, typename T, qualifier Q, bool isSigned = true>
  22. struct compute_ceilPowerOfTwo
  23. {
  24. GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& x)
  25. {
  26. GLM_STATIC_ASSERT(!std::numeric_limits<T>::is_iec559, "'ceilPowerOfTwo' only accept integer scalar or vector inputs");
  27. vec<L, T, Q> const Sign(sign(x));
  28. vec<L, T, Q> v(abs(x));
  29. v = v - static_cast<T>(1);
  30. v = v | (v >> static_cast<T>(1));
  31. v = v | (v >> static_cast<T>(2));
  32. v = v | (v >> static_cast<T>(4));
  33. v = compute_ceilShift<L, T, Q, sizeof(T) >= 2>::call(v, 8);
  34. v = compute_ceilShift<L, T, Q, sizeof(T) >= 4>::call(v, 16);
  35. v = compute_ceilShift<L, T, Q, sizeof(T) >= 8>::call(v, 32);
  36. return (v + static_cast<T>(1)) * Sign;
  37. }
  38. };
  39. template<length_t L, typename T, qualifier Q>
  40. struct compute_ceilPowerOfTwo<L, T, Q, false>
  41. {
  42. GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& x)
  43. {
  44. GLM_STATIC_ASSERT(!std::numeric_limits<T>::is_iec559, "'ceilPowerOfTwo' only accept integer scalar or vector inputs");
  45. vec<L, T, Q> v(x);
  46. v = v - static_cast<T>(1);
  47. v = v | (v >> static_cast<T>(1));
  48. v = v | (v >> static_cast<T>(2));
  49. v = v | (v >> static_cast<T>(4));
  50. v = compute_ceilShift<L, T, Q, sizeof(T) >= 2>::call(v, 8);
  51. v = compute_ceilShift<L, T, Q, sizeof(T) >= 4>::call(v, 16);
  52. v = compute_ceilShift<L, T, Q, sizeof(T) >= 8>::call(v, 32);
  53. return v + static_cast<T>(1);
  54. }
  55. };
  56. template<bool is_float, bool is_signed>
  57. struct compute_ceilMultiple{};
  58. template<>
  59. struct compute_ceilMultiple<true, true>
  60. {
  61. template<typename genType>
  62. GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple)
  63. {
  64. if(Source > genType(0))
  65. return Source + (Multiple - std::fmod(Source, Multiple));
  66. else
  67. return Source + std::fmod(-Source, Multiple);
  68. }
  69. };
  70. template<>
  71. struct compute_ceilMultiple<false, false>
  72. {
  73. template<typename genType>
  74. GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple)
  75. {
  76. genType Tmp = Source - genType(1);
  77. return Tmp + (Multiple - (Tmp % Multiple));
  78. }
  79. };
  80. template<>
  81. struct compute_ceilMultiple<false, true>
  82. {
  83. template<typename genType>
  84. GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple)
  85. {
  86. assert(Multiple > genType(0));
  87. if(Source > genType(0))
  88. {
  89. genType Tmp = Source - genType(1);
  90. return Tmp + (Multiple - (Tmp % Multiple));
  91. }
  92. else
  93. return Source + (-Source % Multiple);
  94. }
  95. };
  96. template<bool is_float, bool is_signed>
  97. struct compute_floorMultiple{};
  98. template<>
  99. struct compute_floorMultiple<true, true>
  100. {
  101. template<typename genType>
  102. GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple)
  103. {
  104. if(Source >= genType(0))
  105. return Source - std::fmod(Source, Multiple);
  106. else
  107. return Source - std::fmod(Source, Multiple) - Multiple;
  108. }
  109. };
  110. template<>
  111. struct compute_floorMultiple<false, false>
  112. {
  113. template<typename genType>
  114. GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple)
  115. {
  116. if(Source >= genType(0))
  117. return Source - Source % Multiple;
  118. else
  119. {
  120. genType Tmp = Source + genType(1);
  121. return Tmp - Tmp % Multiple - Multiple;
  122. }
  123. }
  124. };
  125. template<>
  126. struct compute_floorMultiple<false, true>
  127. {
  128. template<typename genType>
  129. GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple)
  130. {
  131. if(Source >= genType(0))
  132. return Source - Source % Multiple;
  133. else
  134. {
  135. genType Tmp = Source + genType(1);
  136. return Tmp - Tmp % Multiple - Multiple;
  137. }
  138. }
  139. };
  140. }//namespace detail
  141. template<typename genIUType>
  142. GLM_FUNC_QUALIFIER bool isPowerOfTwo(genIUType Value)
  143. {
  144. GLM_STATIC_ASSERT(std::numeric_limits<genIUType>::is_integer, "'isPowerOfTwo' only accept integer inputs");
  145. genIUType const Result = glm::abs(Value);
  146. return !(Result & (Result - 1));
  147. }
  148. template<typename genIUType>
  149. GLM_FUNC_QUALIFIER genIUType nextPowerOfTwo(genIUType value)
  150. {
  151. GLM_STATIC_ASSERT(std::numeric_limits<genIUType>::is_integer, "'nextPowerOfTwo' only accept integer inputs");
  152. return detail::compute_ceilPowerOfTwo<1, genIUType, defaultp, std::numeric_limits<genIUType>::is_signed>::call(vec<1, genIUType, defaultp>(value)).x;
  153. }
  154. template<typename genIUType>
  155. GLM_FUNC_QUALIFIER genIUType prevPowerOfTwo(genIUType value)
  156. {
  157. GLM_STATIC_ASSERT(std::numeric_limits<genIUType>::is_integer, "'prevPowerOfTwo' only accept integer inputs");
  158. return isPowerOfTwo(value) ? value : static_cast<genIUType>(static_cast<genIUType>(1) << static_cast<genIUType>(findMSB(value)));
  159. }
  160. template<typename genIUType>
  161. GLM_FUNC_QUALIFIER bool isMultiple(genIUType Value, genIUType Multiple)
  162. {
  163. GLM_STATIC_ASSERT(std::numeric_limits<genIUType>::is_integer, "'isMultiple' only accept integer inputs");
  164. return isMultiple(vec<1, genIUType>(Value), vec<1, genIUType>(Multiple)).x;
  165. }
  166. template<typename genIUType>
  167. GLM_FUNC_QUALIFIER genIUType nextMultiple(genIUType Source, genIUType Multiple)
  168. {
  169. GLM_STATIC_ASSERT(std::numeric_limits<genIUType>::is_integer, "'nextMultiple' only accept integer inputs");
  170. return detail::compute_ceilMultiple<std::numeric_limits<genIUType>::is_iec559, std::numeric_limits<genIUType>::is_signed>::call(Source, Multiple);
  171. }
  172. template<typename genIUType>
  173. GLM_FUNC_QUALIFIER genIUType prevMultiple(genIUType Source, genIUType Multiple)
  174. {
  175. GLM_STATIC_ASSERT(std::numeric_limits<genIUType>::is_integer, "'prevMultiple' only accept integer inputs");
  176. return detail::compute_floorMultiple<std::numeric_limits<genIUType>::is_iec559, std::numeric_limits<genIUType>::is_signed>::call(Source, Multiple);
  177. }
  178. template<typename genIUType>
  179. GLM_FUNC_QUALIFIER int findNSB(genIUType x, int significantBitCount)
  180. {
  181. GLM_STATIC_ASSERT(std::numeric_limits<genIUType>::is_integer, "'findNSB' only accept integer inputs");
  182. if(bitCount(x) < significantBitCount)
  183. return -1;
  184. genIUType const One = static_cast<genIUType>(1);
  185. int bitPos = 0;
  186. genIUType key = x;
  187. int nBitCount = significantBitCount;
  188. int Step = sizeof(x) * 8 / 2;
  189. while (key > One)
  190. {
  191. genIUType Mask = static_cast<genIUType>((One << Step) - One);
  192. genIUType currentKey = key & Mask;
  193. int currentBitCount = bitCount(currentKey);
  194. if (nBitCount > currentBitCount)
  195. {
  196. nBitCount -= currentBitCount;
  197. bitPos += Step;
  198. key >>= static_cast<genIUType>(Step);
  199. }
  200. else
  201. {
  202. key = key & Mask;
  203. }
  204. Step >>= 1;
  205. }
  206. return static_cast<int>(bitPos);
  207. }
  208. }//namespace glm