round.inl 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. /// @ref gtc_round
  2. #include "../integer.hpp"
  3. namespace glm{
  4. namespace detail
  5. {
  6. template<length_t L, typename T, qualifier Q, bool compute = false>
  7. struct compute_ceilShift
  8. {
  9. GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& v, T)
  10. {
  11. return v;
  12. }
  13. };
  14. template<length_t L, typename T, qualifier Q>
  15. struct compute_ceilShift<L, T, Q, true>
  16. {
  17. GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& v, T Shift)
  18. {
  19. return v | (v >> Shift);
  20. }
  21. };
  22. template<length_t L, typename T, qualifier Q, bool isSigned = true>
  23. struct compute_ceilPowerOfTwo
  24. {
  25. GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& x)
  26. {
  27. GLM_STATIC_ASSERT(!std::numeric_limits<T>::is_iec559, "'ceilPowerOfTwo' only accept integer scalar or vector inputs");
  28. vec<L, T, Q> const Sign(sign(x));
  29. vec<L, T, Q> v(abs(x));
  30. v = v - static_cast<T>(1);
  31. v = v | (v >> static_cast<T>(1));
  32. v = v | (v >> static_cast<T>(2));
  33. v = v | (v >> static_cast<T>(4));
  34. v = compute_ceilShift<L, T, Q, sizeof(T) >= 2>::call(v, 8);
  35. v = compute_ceilShift<L, T, Q, sizeof(T) >= 4>::call(v, 16);
  36. v = compute_ceilShift<L, T, Q, sizeof(T) >= 8>::call(v, 32);
  37. return (v + static_cast<T>(1)) * Sign;
  38. }
  39. };
  40. template<length_t L, typename T, qualifier Q>
  41. struct compute_ceilPowerOfTwo<L, T, Q, false>
  42. {
  43. GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& x)
  44. {
  45. GLM_STATIC_ASSERT(!std::numeric_limits<T>::is_iec559, "'ceilPowerOfTwo' only accept integer scalar or vector inputs");
  46. vec<L, T, Q> v(x);
  47. v = v - static_cast<T>(1);
  48. v = v | (v >> static_cast<T>(1));
  49. v = v | (v >> static_cast<T>(2));
  50. v = v | (v >> static_cast<T>(4));
  51. v = compute_ceilShift<L, T, Q, sizeof(T) >= 2>::call(v, 8);
  52. v = compute_ceilShift<L, T, Q, sizeof(T) >= 4>::call(v, 16);
  53. v = compute_ceilShift<L, T, Q, sizeof(T) >= 8>::call(v, 32);
  54. return v + static_cast<T>(1);
  55. }
  56. };
  57. template<bool is_float, bool is_signed>
  58. struct compute_ceilMultiple{};
  59. template<>
  60. struct compute_ceilMultiple<true, true>
  61. {
  62. template<typename genType>
  63. GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple)
  64. {
  65. if(Source > genType(0))
  66. return Source + (Multiple - std::fmod(Source, Multiple));
  67. else
  68. return Source + std::fmod(-Source, Multiple);
  69. }
  70. };
  71. template<>
  72. struct compute_ceilMultiple<false, false>
  73. {
  74. template<typename genType>
  75. GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple)
  76. {
  77. genType Tmp = Source - genType(1);
  78. return Tmp + (Multiple - (Tmp % Multiple));
  79. }
  80. };
  81. template<>
  82. struct compute_ceilMultiple<false, true>
  83. {
  84. template<typename genType>
  85. GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple)
  86. {
  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. template<bool is_float, bool is_signed>
  141. struct compute_roundMultiple{};
  142. template<>
  143. struct compute_roundMultiple<true, true>
  144. {
  145. template<typename genType>
  146. GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple)
  147. {
  148. if(Source >= genType(0))
  149. return Source - std::fmod(Source, Multiple);
  150. else
  151. {
  152. genType Tmp = Source + genType(1);
  153. return Tmp - std::fmod(Tmp, Multiple) - Multiple;
  154. }
  155. }
  156. };
  157. template<>
  158. struct compute_roundMultiple<false, false>
  159. {
  160. template<typename genType>
  161. GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple)
  162. {
  163. if(Source >= genType(0))
  164. return Source - Source % Multiple;
  165. else
  166. {
  167. genType Tmp = Source + genType(1);
  168. return Tmp - Tmp % Multiple - Multiple;
  169. }
  170. }
  171. };
  172. template<>
  173. struct compute_roundMultiple<false, true>
  174. {
  175. template<typename genType>
  176. GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple)
  177. {
  178. if(Source >= genType(0))
  179. return Source - Source % Multiple;
  180. else
  181. {
  182. genType Tmp = Source + genType(1);
  183. return Tmp - Tmp % Multiple - Multiple;
  184. }
  185. }
  186. };
  187. }//namespace detail
  188. ////////////////
  189. // isPowerOfTwo
  190. template<typename genType>
  191. GLM_FUNC_QUALIFIER bool isPowerOfTwo(genType Value)
  192. {
  193. genType const Result = glm::abs(Value);
  194. return !(Result & (Result - 1));
  195. }
  196. template<length_t L, typename T, qualifier Q>
  197. GLM_FUNC_QUALIFIER vec<L, bool, Q> isPowerOfTwo(vec<L, T, Q> const& Value)
  198. {
  199. vec<L, T, Q> const Result(abs(Value));
  200. return equal(Result & (Result - 1), vec<L, T, Q>(0));
  201. }
  202. //////////////////
  203. // ceilPowerOfTwo
  204. template<typename genType>
  205. GLM_FUNC_QUALIFIER genType ceilPowerOfTwo(genType value)
  206. {
  207. return detail::compute_ceilPowerOfTwo<1, genType, defaultp, std::numeric_limits<genType>::is_signed>::call(vec<1, genType, defaultp>(value)).x;
  208. }
  209. template<length_t L, typename T, qualifier Q>
  210. GLM_FUNC_QUALIFIER vec<L, T, Q> ceilPowerOfTwo(vec<L, T, Q> const& v)
  211. {
  212. return detail::compute_ceilPowerOfTwo<L, T, Q, std::numeric_limits<T>::is_signed>::call(v);
  213. }
  214. ///////////////////
  215. // floorPowerOfTwo
  216. template<typename genType>
  217. GLM_FUNC_QUALIFIER genType floorPowerOfTwo(genType value)
  218. {
  219. return isPowerOfTwo(value) ? value : static_cast<genType>(1) << findMSB(value);
  220. }
  221. template<length_t L, typename T, qualifier Q>
  222. GLM_FUNC_QUALIFIER vec<L, T, Q> floorPowerOfTwo(vec<L, T, Q> const& v)
  223. {
  224. return detail::functor1<vec, L, T, T, Q>::call(floorPowerOfTwo, v);
  225. }
  226. ///////////////////
  227. // roundPowerOfTwo
  228. template<typename genIUType>
  229. GLM_FUNC_QUALIFIER genIUType roundPowerOfTwo(genIUType value)
  230. {
  231. if(isPowerOfTwo(value))
  232. return value;
  233. genIUType const prev = static_cast<genIUType>(1) << findMSB(value);
  234. genIUType const next = prev << static_cast<genIUType>(1);
  235. return (next - value) < (value - prev) ? next : prev;
  236. }
  237. template<length_t L, typename T, qualifier Q>
  238. GLM_FUNC_QUALIFIER vec<L, T, Q> roundPowerOfTwo(vec<L, T, Q> const& v)
  239. {
  240. return detail::functor1<vec, L, T, T, Q>::call(roundPowerOfTwo, v);
  241. }
  242. ////////////////
  243. // isMultiple
  244. template<typename genType>
  245. GLM_FUNC_QUALIFIER bool isMultiple(genType Value, genType Multiple)
  246. {
  247. return isMultiple(vec<1, genType>(Value), vec<1, genType>(Multiple)).x;
  248. }
  249. template<length_t L, typename T, qualifier Q>
  250. GLM_FUNC_QUALIFIER vec<L, bool, Q> isMultiple(vec<L, T, Q> const& Value, T Multiple)
  251. {
  252. return (Value % Multiple) == vec<L, T, Q>(0);
  253. }
  254. template<length_t L, typename T, qualifier Q>
  255. GLM_FUNC_QUALIFIER vec<L, bool, Q> isMultiple(vec<L, T, Q> const& Value, vec<L, T, Q> const& Multiple)
  256. {
  257. return (Value % Multiple) == vec<L, T, Q>(0);
  258. }
  259. //////////////////////
  260. // ceilMultiple
  261. template<typename genType>
  262. GLM_FUNC_QUALIFIER genType ceilMultiple(genType Source, genType Multiple)
  263. {
  264. return detail::compute_ceilMultiple<std::numeric_limits<genType>::is_iec559, std::numeric_limits<genType>::is_signed>::call(Source, Multiple);
  265. }
  266. template<length_t L, typename T, qualifier Q>
  267. GLM_FUNC_QUALIFIER vec<L, T, Q> ceilMultiple(vec<L, T, Q> const& Source, vec<L, T, Q> const& Multiple)
  268. {
  269. return detail::functor2<vec, L, T, Q>::call(ceilMultiple, Source, Multiple);
  270. }
  271. //////////////////////
  272. // floorMultiple
  273. template<typename genType>
  274. GLM_FUNC_QUALIFIER genType floorMultiple(genType Source, genType Multiple)
  275. {
  276. return detail::compute_floorMultiple<std::numeric_limits<genType>::is_iec559, std::numeric_limits<genType>::is_signed>::call(Source, Multiple);
  277. }
  278. template<length_t L, typename T, qualifier Q>
  279. GLM_FUNC_QUALIFIER vec<L, T, Q> floorMultiple(vec<L, T, Q> const& Source, vec<L, T, Q> const& Multiple)
  280. {
  281. return detail::functor2<vec, L, T, Q>::call(floorMultiple, Source, Multiple);
  282. }
  283. //////////////////////
  284. // roundMultiple
  285. template<typename genType>
  286. GLM_FUNC_QUALIFIER genType roundMultiple(genType Source, genType Multiple)
  287. {
  288. return detail::compute_roundMultiple<std::numeric_limits<genType>::is_iec559, std::numeric_limits<genType>::is_signed>::call(Source, Multiple);
  289. }
  290. template<length_t L, typename T, qualifier Q>
  291. GLM_FUNC_QUALIFIER vec<L, T, Q> roundMultiple(vec<L, T, Q> const& Source, vec<L, T, Q> const& Multiple)
  292. {
  293. return detail::functor2<vec, L, T, Q>::call(roundMultiple, Source, Multiple);
  294. }
  295. }//namespace glm