Collection of DPF-based plugins for packaging
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.

345 lines
9.1KB

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