/glm/gtx/ulp.inl

https://bitbucket.org/ggerganov/test_opengl · C++ Header · 299 lines · 248 code · 32 blank · 19 comment · 56 complexity · cf25eb10af997fd49dae0cc839970cbf MD5 · raw file

  1. ///////////////////////////////////////////////////////////////////////////////////////////////////
  2. // OpenGL Mathematics Copyright (c) 2005 - 2012 G-Truc Creation (www.g-truc.net)
  3. ///////////////////////////////////////////////////////////////////////////////////////////////////
  4. // Created : 2011-03-07
  5. // Updated : 2011-04-26
  6. // Licence : This source is under MIT License
  7. // File : glm/gtx/ulp.inl
  8. ///////////////////////////////////////////////////////////////////////////////////////////////////
  9. #include <cmath>
  10. #include <cfloat>
  11. /*
  12. * ====================================================
  13. * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
  14. *
  15. * Developed at SunPro, a Sun Microsystems, Inc. business.
  16. * Permission to use, copy, modify, and distribute this
  17. * software is freely granted, provided that this notice
  18. * is preserved.
  19. * ====================================================
  20. */
  21. #pragma warning(push)
  22. #pragma warning(disable : 4127)
  23. typedef union
  24. {
  25. float value;
  26. /* FIXME: Assumes 32 bit int. */
  27. unsigned int word;
  28. } ieee_float_shape_type;
  29. typedef union
  30. {
  31. double value;
  32. struct
  33. {
  34. glm::detail::int32 lsw;
  35. glm::detail::int32 msw;
  36. } parts;
  37. } ieee_double_shape_type;
  38. #define GLM_EXTRACT_WORDS(ix0,ix1,d) \
  39. do { \
  40. ieee_double_shape_type ew_u; \
  41. ew_u.value = (d); \
  42. (ix0) = ew_u.parts.msw; \
  43. (ix1) = ew_u.parts.lsw; \
  44. } while (0)
  45. #define GLM_GET_FLOAT_WORD(i,d) \
  46. do { \
  47. ieee_float_shape_type gf_u; \
  48. gf_u.value = (d); \
  49. (i) = gf_u.word; \
  50. } while (0)
  51. #define GLM_SET_FLOAT_WORD(d,i) \
  52. do { \
  53. ieee_float_shape_type sf_u; \
  54. sf_u.word = (i); \
  55. (d) = sf_u.value; \
  56. } while (0)
  57. #define GLM_INSERT_WORDS(d,ix0,ix1) \
  58. do { \
  59. ieee_double_shape_type iw_u; \
  60. iw_u.parts.msw = (ix0); \
  61. iw_u.parts.lsw = (ix1); \
  62. (d) = iw_u.value; \
  63. } while (0)
  64. namespace glm{
  65. namespace detail
  66. {
  67. GLM_FUNC_QUALIFIER float nextafterf(float x, float y)
  68. {
  69. volatile float t;
  70. glm::detail::int32 hx, hy, ix, iy;
  71. GLM_GET_FLOAT_WORD(hx, x);
  72. GLM_GET_FLOAT_WORD(hy, y);
  73. ix = hx&0x7fffffff; // |x|
  74. iy = hy&0x7fffffff; // |y|
  75. if((ix>0x7f800000) || // x is nan
  76. (iy>0x7f800000)) // y is nan
  77. return x+y;
  78. if(x==y) return y; // x=y, return y
  79. if(ix==0) { // x == 0
  80. GLM_SET_FLOAT_WORD(x,(hy&0x80000000)|1);// return +-minsubnormal
  81. t = x*x;
  82. if(t==x) return t; else return x; // raise underflow flag
  83. }
  84. if(hx>=0) { // x > 0
  85. if(hx>hy) { // x > y, x -= ulp
  86. hx -= 1;
  87. } else { // x < y, x += ulp
  88. hx += 1;
  89. }
  90. } else { // x < 0
  91. if(hy>=0||hx>hy){ // x < y, x -= ulp
  92. hx -= 1;
  93. } else { // x > y, x += ulp
  94. hx += 1;
  95. }
  96. }
  97. hy = hx&0x7f800000;
  98. if(hy>=0x7f800000) return x+x; // overflow
  99. if(hy<0x00800000) { // underflow
  100. t = x*x;
  101. if(t!=x) { // raise underflow flag
  102. GLM_SET_FLOAT_WORD(y,hx);
  103. return y;
  104. }
  105. }
  106. GLM_SET_FLOAT_WORD(x,hx);
  107. return x;
  108. }
  109. GLM_FUNC_QUALIFIER double nextafter(double x, double y)
  110. {
  111. volatile double t;
  112. glm::detail::int32 hx, hy, ix, iy;
  113. glm::detail::uint32 lx, ly;
  114. GLM_EXTRACT_WORDS(hx, lx, x);
  115. GLM_EXTRACT_WORDS(hy, ly, y);
  116. ix = hx & 0x7fffffff; // |x|
  117. iy = hy & 0x7fffffff; // |y|
  118. if(((ix>=0x7ff00000)&&((ix-0x7ff00000)|lx)!=0) || // x is nan
  119. ((iy>=0x7ff00000)&&((iy-0x7ff00000)|ly)!=0)) // y is nan
  120. return x+y;
  121. if(x==y) return y; // x=y, return y
  122. if((ix|lx)==0) { // x == 0
  123. GLM_INSERT_WORDS(x, hy & 0x80000000, 1); // return +-minsubnormal
  124. t = x*x;
  125. if(t==x) return t; else return x; // raise underflow flag
  126. }
  127. if(hx>=0) { // x > 0
  128. if(hx>hy||((hx==hy)&&(lx>ly))) { // x > y, x -= ulp
  129. if(lx==0) hx -= 1;
  130. lx -= 1;
  131. } else { // x < y, x += ulp
  132. lx += 1;
  133. if(lx==0) hx += 1;
  134. }
  135. } else { // x < 0
  136. if(hy>=0||hx>hy||((hx==hy)&&(lx>ly))){// x < y, x -= ulp
  137. if(lx==0) hx -= 1;
  138. lx -= 1;
  139. } else { // x > y, x += ulp
  140. lx += 1;
  141. if(lx==0) hx += 1;
  142. }
  143. }
  144. hy = hx&0x7ff00000;
  145. if(hy>=0x7ff00000) return x+x; // overflow
  146. if(hy<0x00100000) { // underflow
  147. t = x*x;
  148. if(t!=x) { // raise underflow flag
  149. GLM_INSERT_WORDS(y,hx,lx);
  150. return y;
  151. }
  152. }
  153. GLM_INSERT_WORDS(x,hx,lx);
  154. return x;
  155. }
  156. }//namespace detail
  157. }//namespace glm
  158. #pragma warning(pop)
  159. #if(GLM_COMPILER & GLM_COMPILER_VC || GLM_COMPILER & GLM_COMPILER_INTEL)
  160. # define GLM_NEXT_AFTER_FLT(x, toward) glm::detail::nextafterf((x), (toward))
  161. # define GLM_NEXT_AFTER_DBL(x, toward) _nextafter((x), (toward))
  162. #else
  163. # define GLM_NEXT_AFTER_FLT(x, toward) nextafterf((x), (toward))
  164. # define GLM_NEXT_AFTER_DBL(x, toward) nextafter((x), (toward))
  165. #endif
  166. namespace glm
  167. {
  168. GLM_FUNC_QUALIFIER float next_float(float const & x)
  169. {
  170. return GLM_NEXT_AFTER_FLT(x, std::numeric_limits<float>::max());
  171. }
  172. GLM_FUNC_QUALIFIER double next_float(double const & x)
  173. {
  174. return GLM_NEXT_AFTER_DBL(x, std::numeric_limits<double>::max());
  175. }
  176. template<typename T, template<typename> class vecType>
  177. GLM_FUNC_QUALIFIER vecType<T> next_float(vecType<T> const & x)
  178. {
  179. vecType<T> Result;
  180. for(std::size_t i = 0; i < Result.length(); ++i)
  181. Result[i] = next_float(x[i]);
  182. return Result;
  183. }
  184. GLM_FUNC_QUALIFIER float prev_float(float const & x)
  185. {
  186. return GLM_NEXT_AFTER_FLT(x, std::numeric_limits<float>::min());
  187. }
  188. GLM_FUNC_QUALIFIER double prev_float(double const & x)
  189. {
  190. return GLM_NEXT_AFTER_DBL(x, std::numeric_limits<double>::min());
  191. }
  192. template<typename T, template<typename> class vecType>
  193. GLM_FUNC_QUALIFIER vecType<T> prev_float(vecType<T> const & x)
  194. {
  195. vecType<T> Result;
  196. for(std::size_t i = 0; i < Result.length(); ++i)
  197. Result[i] = prev_float(x[i]);
  198. return Result;
  199. }
  200. template <typename T>
  201. GLM_FUNC_QUALIFIER T next_float(T const & x, uint const & ulps)
  202. {
  203. T temp = x;
  204. for(std::size_t i = 0; i < ulps; ++i)
  205. temp = next_float(temp);
  206. return temp;
  207. }
  208. template<typename T, template<typename> class vecType>
  209. GLM_FUNC_QUALIFIER vecType<T> next_float(vecType<T> const & x, vecType<uint> const & ulps)
  210. {
  211. vecType<T> Result;
  212. for(std::size_t i = 0; i < Result.length(); ++i)
  213. Result[i] = next_float(x[i], ulps[i]);
  214. return Result;
  215. }
  216. template <typename T>
  217. GLM_FUNC_QUALIFIER T prev_float(T const & x, uint const & ulps)
  218. {
  219. T temp = x;
  220. for(std::size_t i = 0; i < ulps; ++i)
  221. temp = prev_float(temp);
  222. return temp;
  223. }
  224. template<typename T, template<typename> class vecType>
  225. GLM_FUNC_QUALIFIER vecType<T> prev_float(vecType<T> const & x, vecType<uint> const & ulps)
  226. {
  227. vecType<T> Result;
  228. for(std::size_t i = 0; i < Result.length(); ++i)
  229. Result[i] = prev_float(x[i], ulps[i]);
  230. return Result;
  231. }
  232. template <typename T>
  233. GLM_FUNC_QUALIFIER uint float_distance(T const & x, T const & y)
  234. {
  235. uint ulp = 0;
  236. if(x < y)
  237. {
  238. T temp = x;
  239. while(temp != y && ulp < std::numeric_limits<std::size_t>::max())
  240. {
  241. ++ulp;
  242. temp = next_float(temp);
  243. }
  244. }
  245. else if(y < x)
  246. {
  247. T temp = y;
  248. while(temp != x && ulp < std::numeric_limits<std::size_t>::max())
  249. {
  250. ++ulp;
  251. temp = next_float(temp);
  252. }
  253. }
  254. else // ==
  255. {
  256. }
  257. return ulp;
  258. }
  259. template<typename T, template<typename> class vecType>
  260. GLM_FUNC_QUALIFIER vecType<uint> float_distance(vecType<T> const & x, vecType<T> const & y)
  261. {
  262. vecType<uint> Result;
  263. for(std::size_t i = 0; i < Result.length(); ++i)
  264. Result[i] = float_distance(x[i], y[i]);
  265. return Result;
  266. }
  267. }//namespace glm