ulp.inl 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. /// @ref gtc_ulp
  2. #include "../ext/scalar_ulp.hpp"
  3. namespace glm
  4. {
  5. template<>
  6. GLM_FUNC_QUALIFIER float next_float(float x)
  7. {
  8. # if GLM_HAS_CXX11_STL
  9. return std::nextafter(x, std::numeric_limits<float>::max());
  10. # elif((GLM_COMPILER & GLM_COMPILER_VC) || ((GLM_COMPILER & GLM_COMPILER_INTEL) && (GLM_PLATFORM & GLM_PLATFORM_WINDOWS)))
  11. return detail::nextafterf(x, FLT_MAX);
  12. # elif(GLM_PLATFORM & GLM_PLATFORM_ANDROID)
  13. return __builtin_nextafterf(x, FLT_MAX);
  14. # else
  15. return nextafterf(x, FLT_MAX);
  16. # endif
  17. }
  18. template<>
  19. GLM_FUNC_QUALIFIER double next_float(double x)
  20. {
  21. # if GLM_HAS_CXX11_STL
  22. return std::nextafter(x, std::numeric_limits<double>::max());
  23. # elif((GLM_COMPILER & GLM_COMPILER_VC) || ((GLM_COMPILER & GLM_COMPILER_INTEL) && (GLM_PLATFORM & GLM_PLATFORM_WINDOWS)))
  24. return detail::nextafter(x, std::numeric_limits<double>::max());
  25. # elif(GLM_PLATFORM & GLM_PLATFORM_ANDROID)
  26. return __builtin_nextafter(x, DBL_MAX);
  27. # else
  28. return nextafter(x, DBL_MAX);
  29. # endif
  30. }
  31. template<typename T>
  32. GLM_FUNC_QUALIFIER T next_float(T x, int ULPs)
  33. {
  34. GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'next_float' only accept floating-point input");
  35. assert(ULPs >= 0);
  36. T temp = x;
  37. for (int i = 0; i < ULPs; ++i)
  38. temp = next_float(temp);
  39. return temp;
  40. }
  41. GLM_FUNC_QUALIFIER float prev_float(float x)
  42. {
  43. # if GLM_HAS_CXX11_STL
  44. return std::nextafter(x, std::numeric_limits<float>::min());
  45. # elif((GLM_COMPILER & GLM_COMPILER_VC) || ((GLM_COMPILER & GLM_COMPILER_INTEL) && (GLM_PLATFORM & GLM_PLATFORM_WINDOWS)))
  46. return detail::nextafterf(x, FLT_MIN);
  47. # elif(GLM_PLATFORM & GLM_PLATFORM_ANDROID)
  48. return __builtin_nextafterf(x, FLT_MIN);
  49. # else
  50. return nextafterf(x, FLT_MIN);
  51. # endif
  52. }
  53. GLM_FUNC_QUALIFIER double prev_float(double x)
  54. {
  55. # if GLM_HAS_CXX11_STL
  56. return std::nextafter(x, std::numeric_limits<double>::min());
  57. # elif((GLM_COMPILER & GLM_COMPILER_VC) || ((GLM_COMPILER & GLM_COMPILER_INTEL) && (GLM_PLATFORM & GLM_PLATFORM_WINDOWS)))
  58. return _nextafter(x, DBL_MIN);
  59. # elif(GLM_PLATFORM & GLM_PLATFORM_ANDROID)
  60. return __builtin_nextafter(x, DBL_MIN);
  61. # else
  62. return nextafter(x, DBL_MIN);
  63. # endif
  64. }
  65. template<typename T>
  66. GLM_FUNC_QUALIFIER T prev_float(T x, int ULPs)
  67. {
  68. GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'prev_float' only accept floating-point input");
  69. assert(ULPs >= 0);
  70. T temp = x;
  71. for (int i = 0; i < ULPs; ++i)
  72. temp = prev_float(temp);
  73. return temp;
  74. }
  75. GLM_FUNC_QUALIFIER int float_distance(float x, float y)
  76. {
  77. detail::float_t<float> const a(x);
  78. detail::float_t<float> const b(y);
  79. return abs(a.i - b.i);
  80. }
  81. GLM_FUNC_QUALIFIER int64 float_distance(double x, double y)
  82. {
  83. detail::float_t<double> const a(x);
  84. detail::float_t<double> const b(y);
  85. return abs(a.i - b.i);
  86. }
  87. template<length_t L, typename T, qualifier Q>
  88. GLM_FUNC_QUALIFIER vec<L, T, Q> next_float(vec<L, T, Q> const& x)
  89. {
  90. vec<L, T, Q> Result;
  91. for (length_t i = 0, n = Result.length(); i < n; ++i)
  92. Result[i] = next_float(x[i]);
  93. return Result;
  94. }
  95. template<length_t L, typename T, qualifier Q>
  96. GLM_FUNC_QUALIFIER vec<L, T, Q> next_float(vec<L, T, Q> const& x, int ULPs)
  97. {
  98. vec<L, T, Q> Result;
  99. for (length_t i = 0, n = Result.length(); i < n; ++i)
  100. Result[i] = next_float(x[i], ULPs);
  101. return Result;
  102. }
  103. template<length_t L, typename T, qualifier Q>
  104. GLM_FUNC_QUALIFIER vec<L, T, Q> next_float(vec<L, T, Q> const& x, vec<L, int, Q> const& ULPs)
  105. {
  106. vec<L, T, Q> Result;
  107. for (length_t i = 0, n = Result.length(); i < n; ++i)
  108. Result[i] = next_float(x[i], ULPs[i]);
  109. return Result;
  110. }
  111. template<length_t L, typename T, qualifier Q>
  112. GLM_FUNC_QUALIFIER vec<L, T, Q> prev_float(vec<L, T, Q> const& x)
  113. {
  114. vec<L, T, Q> Result;
  115. for (length_t i = 0, n = Result.length(); i < n; ++i)
  116. Result[i] = prev_float(x[i]);
  117. return Result;
  118. }
  119. template<length_t L, typename T, qualifier Q>
  120. GLM_FUNC_QUALIFIER vec<L, T, Q> prev_float(vec<L, T, Q> const& x, int ULPs)
  121. {
  122. vec<L, T, Q> Result;
  123. for (length_t i = 0, n = Result.length(); i < n; ++i)
  124. Result[i] = prev_float(x[i], ULPs);
  125. return Result;
  126. }
  127. template<length_t L, typename T, qualifier Q>
  128. GLM_FUNC_QUALIFIER vec<L, T, Q> prev_float(vec<L, T, Q> const& x, vec<L, int, Q> const& ULPs)
  129. {
  130. vec<L, T, Q> Result;
  131. for (length_t i = 0, n = Result.length(); i < n; ++i)
  132. Result[i] = prev_float(x[i], ULPs[i]);
  133. return Result;
  134. }
  135. template<length_t L, qualifier Q>
  136. GLM_FUNC_QUALIFIER vec<L, int, Q> float_distance(vec<L, float, Q> const& x, vec<L, float, Q> const& y)
  137. {
  138. vec<L, int, Q> Result;
  139. for (length_t i = 0, n = Result.length(); i < n; ++i)
  140. Result[i] = float_distance(x[i], y[i]);
  141. return Result;
  142. }
  143. template<length_t L, qualifier Q>
  144. GLM_FUNC_QUALIFIER vec<L, int64, Q> float_distance(vec<L, double, Q> const& x, vec<L, double, Q> const& y)
  145. {
  146. vec<L, int64, Q> Result;
  147. for (length_t i = 0, n = Result.length(); i < n; ++i)
  148. Result[i] = float_distance(x[i], y[i]);
  149. return Result;
  150. }
  151. }//namespace glm