parent
32573c86ec
commit
76683aa287
11 changed files with 796 additions and 426 deletions
@ -0,0 +1,73 @@ |
||||
/// @ref ext_scalar_ulp
|
||||
/// @file glm/ext/scalar_ulp.hpp
|
||||
///
|
||||
/// @defgroup ext_scalar_ulp GLM_EXT_scalar_ulp
|
||||
/// @ingroup ext
|
||||
///
|
||||
/// Allow the measurement of the accuracy of a function against a reference
|
||||
/// implementation. This extension works on floating-point data and provide results
|
||||
/// in ULP.
|
||||
///
|
||||
/// Include <glm/ext/scalar_ulp.hpp> to use the features of this extension.
|
||||
///
|
||||
/// @see ext_vector_ulp
|
||||
/// @see ext_scalar_relational
|
||||
|
||||
#pragma once |
||||
|
||||
// Dependencies
|
||||
#include "../ext/scalar_int_sized.hpp" |
||||
#include "../detail/qualifier.hpp" |
||||
|
||||
#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) |
||||
# pragma message("GLM: GLM_EXT_scalar_ulp extension included") |
||||
#endif |
||||
|
||||
namespace glm |
||||
{ |
||||
/// Return the next ULP value(s) after the input value(s).
|
||||
///
|
||||
/// @tparam genType A floating-point scalar type.
|
||||
///
|
||||
/// @see ext_scalar_ulp
|
||||
template<typename genType> |
||||
GLM_FUNC_DECL genType next_float(genType x); |
||||
|
||||
/// Return the previous ULP value(s) before the input value(s).
|
||||
///
|
||||
/// @tparam genType A floating-point scalar type.
|
||||
///
|
||||
/// @see ext_scalar_ulp
|
||||
template<typename genType> |
||||
GLM_FUNC_DECL genType prev_float(genType x); |
||||
|
||||
/// Return the value(s) ULP distance after the input value(s).
|
||||
///
|
||||
/// @tparam genType A floating-point scalar type.
|
||||
///
|
||||
/// @see ext_scalar_ulp
|
||||
template<typename genType> |
||||
GLM_FUNC_DECL genType next_float(genType x, int ULPs); |
||||
|
||||
/// Return the value(s) ULP distance before the input value(s).
|
||||
///
|
||||
/// @tparam genType A floating-point scalar type.
|
||||
///
|
||||
/// @see ext_scalar_ulp
|
||||
template<typename genType> |
||||
GLM_FUNC_DECL genType prev_float(genType x, int ULPs); |
||||
|
||||
/// Return the distance in the number of ULP between 2 single-precision floating-point scalars.
|
||||
///
|
||||
/// @see ext_scalar_ulp
|
||||
GLM_FUNC_DECL int float_distance(float x, float y); |
||||
|
||||
/// Return the distance in the number of ULP between 2 double-precision floating-point scalars.
|
||||
///
|
||||
/// @see ext_scalar_ulp
|
||||
GLM_FUNC_DECL int64 float_distance(double x, double y); |
||||
|
||||
/// @}
|
||||
}//namespace glm
|
||||
|
||||
#include "scalar_ulp.inl" |
@ -0,0 +1,282 @@ |
||||
/// Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. |
||||
/// |
||||
/// Developed at SunPro, a Sun Microsystems, Inc. business. |
||||
/// Permission to use, copy, modify, and distribute this |
||||
/// software is freely granted, provided that this notice |
||||
/// is preserved. |
||||
|
||||
#include "../detail/type_float.hpp" |
||||
#include "../ext/scalar_constants.hpp" |
||||
|
||||
#if(GLM_COMPILER & GLM_COMPILER_VC) |
||||
# pragma warning(push) |
||||
# pragma warning(disable : 4127) |
||||
#endif |
||||
|
||||
typedef union |
||||
{ |
||||
float value; |
||||
/* FIXME: Assumes 32 bit int. */ |
||||
unsigned int word; |
||||
} ieee_float_shape_type; |
||||
|
||||
typedef union |
||||
{ |
||||
double value; |
||||
struct |
||||
{ |
||||
int lsw; |
||||
int msw; |
||||
} parts; |
||||
} ieee_double_shape_type; |
||||
|
||||
#define GLM_EXTRACT_WORDS(ix0,ix1,d) \ |
||||
do { \ |
||||
ieee_double_shape_type ew_u; \ |
||||
ew_u.value = (d); \ |
||||
(ix0) = ew_u.parts.msw; \ |
||||
(ix1) = ew_u.parts.lsw; \ |
||||
} while (0) |
||||
|
||||
#define GLM_GET_FLOAT_WORD(i,d) \ |
||||
do { \ |
||||
ieee_float_shape_type gf_u; \ |
||||
gf_u.value = (d); \ |
||||
(i) = gf_u.word; \ |
||||
} while (0) |
||||
|
||||
#define GLM_SET_FLOAT_WORD(d,i) \ |
||||
do { \ |
||||
ieee_float_shape_type sf_u; \ |
||||
sf_u.word = (i); \ |
||||
(d) = sf_u.value; \ |
||||
} while (0) |
||||
|
||||
#define GLM_INSERT_WORDS(d,ix0,ix1) \ |
||||
do { \ |
||||
ieee_double_shape_type iw_u; \ |
||||
iw_u.parts.msw = (ix0); \ |
||||
iw_u.parts.lsw = (ix1); \ |
||||
(d) = iw_u.value; \ |
||||
} while (0) |
||||
|
||||
namespace glm{ |
||||
namespace detail |
||||
{ |
||||
GLM_FUNC_QUALIFIER float nextafterf(float x, float y) |
||||
{ |
||||
volatile float t; |
||||
int hx, hy, ix, iy; |
||||
|
||||
GLM_GET_FLOAT_WORD(hx, x); |
||||
GLM_GET_FLOAT_WORD(hy, y); |
||||
ix = hx & 0x7fffffff; // |x| |
||||
iy = hy & 0x7fffffff; // |y| |
||||
|
||||
if((ix > 0x7f800000) || // x is nan |
||||
(iy > 0x7f800000)) // y is nan |
||||
return x + y; |
||||
if(abs(y - x) <= epsilon<float>()) |
||||
return y; // x=y, return y |
||||
if(ix == 0) |
||||
{ // x == 0 |
||||
GLM_SET_FLOAT_WORD(x, (hy & 0x80000000) | 1);// return +-minsubnormal |
||||
t = x * x; |
||||
if(abs(t - x) <= epsilon<float>()) |
||||
return t; |
||||
else |
||||
return x; // raise underflow flag |
||||
} |
||||
if(hx >= 0) |
||||
{ // x > 0 |
||||
if(hx > hy) // x > y, x -= ulp |
||||
hx -= 1; |
||||
else // x < y, x += ulp |
||||
hx += 1; |
||||
} |
||||
else |
||||
{ // x < 0 |
||||
if(hy >= 0 || hx > hy) // x < y, x -= ulp |
||||
hx -= 1; |
||||
else // x > y, x += ulp |
||||
hx += 1; |
||||
} |
||||
hy = hx & 0x7f800000; |
||||
if(hy >= 0x7f800000) |
||||
return x + x; // overflow |
||||
if(hy < 0x00800000) // underflow |
||||
{ |
||||
t = x * x; |
||||
if(abs(t - x) > epsilon<float>()) |
||||
{ // raise underflow flag |
||||
GLM_SET_FLOAT_WORD(y, hx); |
||||
return y; |
||||
} |
||||
} |
||||
GLM_SET_FLOAT_WORD(x, hx); |
||||
return x; |
||||
} |
||||
|
||||
GLM_FUNC_QUALIFIER double nextafter(double x, double y) |
||||
{ |
||||
volatile double t; |
||||
int hx, hy, ix, iy; |
||||
unsigned int lx, ly; |
||||
|
||||
GLM_EXTRACT_WORDS(hx, lx, x); |
||||
GLM_EXTRACT_WORDS(hy, ly, y); |
||||
ix = hx & 0x7fffffff; // |x| |
||||
iy = hy & 0x7fffffff; // |y| |
||||
|
||||
if(((ix >= 0x7ff00000) && ((ix - 0x7ff00000) | lx) != 0) || // x is nan |
||||
((iy >= 0x7ff00000) && ((iy - 0x7ff00000) | ly) != 0)) // y is nan |
||||
return x + y; |
||||
if(abs(y - x) <= epsilon<double>()) |
||||
return y; // x=y, return y |
||||
if((ix | lx) == 0) |
||||
{ // x == 0 |
||||
GLM_INSERT_WORDS(x, hy & 0x80000000, 1); // return +-minsubnormal |
||||
t = x * x; |
||||
if(abs(t - x) <= epsilon<double>()) |
||||
return t; |
||||
else |
||||
return x; // raise underflow flag |
||||
} |
||||
if(hx >= 0) { // x > 0 |
||||
if(hx > hy || ((hx == hy) && (lx > ly))) { // x > y, x -= ulp |
||||
if(lx == 0) hx -= 1; |
||||
lx -= 1; |
||||
} |
||||
else { // x < y, x += ulp |
||||
lx += 1; |
||||
if(lx == 0) hx += 1; |
||||
} |
||||
} |
||||
else { // x < 0 |
||||
if(hy >= 0 || hx > hy || ((hx == hy) && (lx > ly))){// x < y, x -= ulp |
||||
if(lx == 0) hx -= 1; |
||||
lx -= 1; |
||||
} |
||||
else { // x > y, x += ulp |
||||
lx += 1; |
||||
if(lx == 0) hx += 1; |
||||
} |
||||
} |
||||
hy = hx & 0x7ff00000; |
||||
if(hy >= 0x7ff00000) |
||||
return x + x; // overflow |
||||
if(hy < 0x00100000) |
||||
{ // underflow |
||||
t = x * x; |
||||
if(abs(t - x) > epsilon<double>()) |
||||
{ // raise underflow flag |
||||
GLM_INSERT_WORDS(y, hx, lx); |
||||
return y; |
||||
} |
||||
} |
||||
GLM_INSERT_WORDS(x, hx, lx); |
||||
return x; |
||||
} |
||||
}//namespace detail |
||||
}//namespace glm |
||||
|
||||
#if(GLM_COMPILER & GLM_COMPILER_VC) |
||||
# pragma warning(pop) |
||||
#endif |
||||
|
||||
namespace glm |
||||
{ |
||||
template<> |
||||
GLM_FUNC_QUALIFIER float next_float(float x) |
||||
{ |
||||
# if GLM_HAS_CXX11_STL |
||||
return std::nextafter(x, std::numeric_limits<float>::max()); |
||||
# elif((GLM_COMPILER & GLM_COMPILER_VC) || ((GLM_COMPILER & GLM_COMPILER_INTEL) && (GLM_PLATFORM & GLM_PLATFORM_WINDOWS))) |
||||
return detail::nextafterf(x, FLT_MAX); |
||||
# elif(GLM_PLATFORM & GLM_PLATFORM_ANDROID) |
||||
return __builtin_nextafterf(x, FLT_MAX); |
||||
# else |
||||
return nextafterf(x, FLT_MAX); |
||||
# endif |
||||
} |
||||
|
||||
template<> |
||||
GLM_FUNC_QUALIFIER double next_float(double x) |
||||
{ |
||||
# if GLM_HAS_CXX11_STL |
||||
return std::nextafter(x, std::numeric_limits<double>::max()); |
||||
# elif((GLM_COMPILER & GLM_COMPILER_VC) || ((GLM_COMPILER & GLM_COMPILER_INTEL) && (GLM_PLATFORM & GLM_PLATFORM_WINDOWS))) |
||||
return detail::nextafter(x, std::numeric_limits<double>::max()); |
||||
# elif(GLM_PLATFORM & GLM_PLATFORM_ANDROID) |
||||
return __builtin_nextafter(x, FLT_MAX); |
||||
# else |
||||
return nextafter(x, DBL_MAX); |
||||
# endif |
||||
} |
||||
|
||||
template<typename T> |
||||
GLM_FUNC_QUALIFIER T next_float(T x, int ULPs) |
||||
{ |
||||
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'next_float' only accept floating-point input"); |
||||
assert(ULPs >= 0); |
||||
|
||||
T temp = x; |
||||
for(int i = 0; i < ULPs; ++i) |
||||
temp = next_float(temp); |
||||
return temp; |
||||
} |
||||
|
||||
GLM_FUNC_QUALIFIER float prev_float(float x) |
||||
{ |
||||
# if GLM_HAS_CXX11_STL |
||||
return std::nextafter(x, std::numeric_limits<float>::min()); |
||||
# elif((GLM_COMPILER & GLM_COMPILER_VC) || ((GLM_COMPILER & GLM_COMPILER_INTEL) && (GLM_PLATFORM & GLM_PLATFORM_WINDOWS))) |
||||
return detail::nextafterf(x, FLT_MIN); |
||||
# elif(GLM_PLATFORM & GLM_PLATFORM_ANDROID) |
||||
return __builtin_nextafterf(x, FLT_MIN); |
||||
# else |
||||
return nextafterf(x, FLT_MIN); |
||||
# endif |
||||
} |
||||
|
||||
GLM_FUNC_QUALIFIER double prev_float(double x) |
||||
{ |
||||
# if GLM_HAS_CXX11_STL |
||||
return std::nextafter(x, std::numeric_limits<double>::min()); |
||||
# elif((GLM_COMPILER & GLM_COMPILER_VC) || ((GLM_COMPILER & GLM_COMPILER_INTEL) && (GLM_PLATFORM & GLM_PLATFORM_WINDOWS))) |
||||
return _nextafter(x, DBL_MIN); |
||||
# elif(GLM_PLATFORM & GLM_PLATFORM_ANDROID) |
||||
return __builtin_nextafter(x, DBL_MIN); |
||||
# else |
||||
return nextafter(x, DBL_MIN); |
||||
# endif |
||||
} |
||||
|
||||
template<typename T> |
||||
GLM_FUNC_QUALIFIER T prev_float(T x, int ULPs) |
||||
{ |
||||
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'prev_float' only accept floating-point input"); |
||||
assert(ULPs >= 0); |
||||
|
||||
T temp = x; |
||||
for(int i = 0; i < ULPs; ++i) |
||||
temp = prev_float(temp); |
||||
return temp; |
||||
} |
||||
|
||||
GLM_FUNC_QUALIFIER int float_distance(float x, float y) |
||||
{ |
||||
detail::float_t<float> const a(x); |
||||
detail::float_t<float> const b(y); |
||||
|
||||
return abs(a.i - b.i); |
||||
} |
||||
|
||||
GLM_FUNC_QUALIFIER int64 float_distance(double x, double y) |
||||
{ |
||||
detail::float_t<double> const a(x); |
||||
detail::float_t<double> const b(y); |
||||
|
||||
return abs(a.i - b.i); |
||||
} |
||||
}//namespace glm |
@ -0,0 +1,91 @@ |
||||
/// @ref ext_vector_ulp
|
||||
/// @file glm/ext/vector_ulp.hpp
|
||||
///
|
||||
/// @defgroup ext_vector_ulp GLM_EXT_vector_ulp
|
||||
/// @ingroup ext
|
||||
///
|
||||
/// Allow the measurement of the accuracy of a function against a reference
|
||||
/// implementation. This extension works on floating-point data and provide results
|
||||
/// in ULP.
|
||||
///
|
||||
/// Include <glm/ext/vector_ulp.hpp> to use the features of this extension.
|
||||
///
|
||||
/// @see ext_scalar_ulp
|
||||
/// @see ext_scalar_relational
|
||||
/// @see ext_vector_relational
|
||||
|
||||
#pragma once |
||||
|
||||
// Dependencies
|
||||
#include "../ext/scalar_ulp.hpp" |
||||
|
||||
#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) |
||||
# pragma message("GLM: GLM_EXT_vector_ulp extension included") |
||||
#endif |
||||
|
||||
namespace glm |
||||
{ |
||||
/// Return the next ULP value(s) after the input value(s).
|
||||
///
|
||||
/// @tparam genType A floating-point scalar type.
|
||||
///
|
||||
/// @see ext_scalar_ulp
|
||||
template<length_t L, typename T, qualifier Q> |
||||
GLM_FUNC_DECL vec<L, T, Q> next_float(vec<L, T, Q> const& x); |
||||
|
||||
/// Return the value(s) ULP distance after the input value(s).
|
||||
///
|
||||
/// @tparam genType A floating-point scalar type.
|
||||
///
|
||||
/// @see ext_scalar_ulp
|
||||
template<length_t L, typename T, qualifier Q> |
||||
GLM_FUNC_DECL vec<L, T, Q> next_float(vec<L, T, Q> const& x, int ULPs); |
||||
|
||||
/// Return the value(s) ULP distance after the input value(s).
|
||||
///
|
||||
/// @tparam genType A floating-point scalar type.
|
||||
///
|
||||
/// @see ext_scalar_ulp
|
||||
template<length_t L, typename T, qualifier Q> |
||||
GLM_FUNC_DECL vec<L, T, Q> next_float(vec<L, T, Q> const& x, vec<L, int, Q> const& ULPs); |
||||
|
||||
/// Return the previous ULP value(s) before the input value(s).
|
||||
///
|
||||
/// @tparam genType A floating-point scalar type.
|
||||
///
|
||||
/// @see ext_scalar_ulp
|
||||
template<length_t L, typename T, qualifier Q> |
||||
GLM_FUNC_DECL vec<L, T, Q> prev_float(vec<L, T, Q> const& x); |
||||
|
||||
/// Return the value(s) ULP distance before the input value(s).
|
||||
///
|
||||
/// @tparam genType A floating-point scalar type.
|
||||
///
|
||||
/// @see ext_scalar_ulp
|
||||
template<length_t L, typename T, qualifier Q> |
||||
GLM_FUNC_DECL vec<L, T, Q> prev_float(vec<L, T, Q> const& x, int ULPs); |
||||
|
||||
/// Return the value(s) ULP distance before the input value(s).
|
||||
///
|
||||
/// @tparam genType A floating-point scalar type.
|
||||
///
|
||||
/// @see ext_scalar_ulp
|
||||
template<length_t L, typename T, qualifier Q> |
||||
GLM_FUNC_DECL vec<L, T, Q> prev_float(vec<L, T, Q> const& x, vec<L, int, Q> const& ULPs); |
||||
|
||||
/// Return the distance in the number of ULP between 2 single-precision floating-point scalars.
|
||||
///
|
||||
/// @see ext_scalar_ulp
|
||||
template<length_t L, typename T, qualifier Q> |
||||
GLM_FUNC_DECL vec<L, int, Q> float_distance(vec<L, float, Q> const& x, vec<L, float, Q> const& y); |
||||
|
||||
/// Return the distance in the number of ULP between 2 double-precision floating-point scalars.
|
||||
///
|
||||
/// @see ext_scalar_ulp
|
||||
template<length_t L, typename T, qualifier Q> |
||||
GLM_FUNC_DECL vec<L, int64, Q> float_distance(vec<L, double, Q> const& x, vec<L, double, Q> const& y); |
||||
|
||||
/// @}
|
||||
}//namespace glm
|
||||
|
||||
#include "vector_ulp.inl" |
@ -0,0 +1,74 @@ |
||||
namespace glm |
||||
{ |
||||
template<length_t L, typename T, qualifier Q> |
||||
GLM_FUNC_QUALIFIER vec<L, T, Q> next_float(vec<L, T, Q> const& x) |
||||
{ |
||||
vec<L, T, Q> Result; |
||||
for(length_t i = 0, n = Result.length(); i < n; ++i) |
||||
Result[i] = next_float(x[i]); |
||||
return Result; |
||||
} |
||||
|
||||
template<length_t L, typename T, qualifier Q> |
||||
GLM_FUNC_QUALIFIER vec<L, T, Q> next_float(vec<L, T, Q> const& x, int ULPs) |
||||
{ |
||||
vec<L, T, Q> Result; |
||||
for(length_t i = 0, n = Result.length(); i < n; ++i) |
||||
Result[i] = next_float(x[i], ULPs); |
||||
return Result; |
||||
} |
||||
|
||||
template<length_t L, typename T, qualifier Q> |
||||
GLM_FUNC_QUALIFIER vec<L, T, Q> next_float(vec<L, T, Q> const& x, vec<L, int, Q> const& ULPs) |
||||
{ |
||||
vec<L, T, Q> Result; |
||||
for(length_t i = 0, n = Result.length(); i < n; ++i) |
||||
Result[i] = next_float(x[i], ULPs[i]); |
||||
return Result; |
||||
} |
||||
|
||||
template<length_t L, typename T, qualifier Q> |
||||
GLM_FUNC_QUALIFIER vec<L, T, Q> prev_float(vec<L, T, Q> const& x) |
||||
{ |
||||
vec<L, T, Q> Result; |
||||
for(length_t i = 0, n = Result.length(); i < n; ++i) |
||||
Result[i] = prev_float(x[i]); |
||||
return Result; |
||||
} |
||||
|
||||
template<length_t L, typename T, qualifier Q> |
||||
GLM_FUNC_QUALIFIER vec<L, T, Q> prev_float(vec<L, T, Q> const& x, int ULPs) |
||||
{ |
||||
vec<L, T, Q> Result; |
||||
for(length_t i = 0, n = Result.length(); i < n; ++i) |
||||
Result[i] = prev_float(x[i], ULPs); |
||||
return Result; |
||||
} |
||||
|
||||
template<length_t L, typename T, qualifier Q> |
||||
GLM_FUNC_QUALIFIER vec<L, T, Q> prev_float(vec<L, T, Q> const& x, vec<L, int, Q> const& ULPs) |
||||
{ |
||||
vec<L, T, Q> Result; |
||||
for(length_t i = 0, n = Result.length(); i < n; ++i) |
||||
Result[i] = prev_float(x[i], ULPs[i]); |
||||
return Result; |
||||
} |
||||
|
||||
template<length_t L, qualifier Q> |
||||
GLM_FUNC_QUALIFIER vec<L, int, Q> float_distance(vec<L, float, Q> const& x, vec<L, float, Q> const& y) |
||||
{ |
||||
vec<L, int, Q> Result; |
||||
for(length_t i = 0, n = Result.length(); i < n; ++i) |
||||
Result[i] = float_distance(x[i], y[i]); |
||||
return Result; |
||||
} |
||||
|
||||
template<length_t L, qualifier Q> |
||||
GLM_FUNC_QUALIFIER vec<L, int64, Q> float_distance(vec<L, double, Q> const& x, vec<L, double, Q> const& y) |
||||
{ |
||||
vec<L, int64, Q> Result; |
||||
for(length_t i = 0, n = Result.length(); i < n; ++i) |
||||
Result[i] = float_distance(x[i], y[i]); |
||||
return Result; |
||||
} |
||||
}//namespace glm |
@ -0,0 +1,96 @@ |
||||
#include <glm/ext/scalar_ulp.hpp> |
||||
#include <glm/ext/scalar_relational.hpp> |
||||
|
||||
static int test_ulp_float_dist() |
||||
{ |
||||
int Error = 0; |
||||
|
||||
float A = 1.0f; |
||||
|
||||
float B = glm::next_float(A); |
||||
Error += glm::notEqual(A, B, 0) ? 0 : 1; |
||||
float C = glm::prev_float(B); |
||||
Error += glm::equal(A, C, 0) ? 0 : 1; |
||||
|
||||
int D = glm::float_distance(A, B); |
||||
Error += D == 1 ? 0 : 1; |
||||
int E = glm::float_distance(A, C); |
||||
Error += E == 0 ? 0 : 1; |
||||
|
||||
return Error; |
||||
} |
||||
|
||||
static int test_ulp_float_step() |
||||
{ |
||||
int Error = 0; |
||||
|
||||
float A = 1.0f; |
||||
|
||||
for(int i = 10; i < 1000; i *= 10) |
||||
{ |
||||
float B = glm::next_float(A, i); |
||||
Error += glm::notEqual(A, B, 0) ? 0 : 1; |
||||
float C = glm::prev_float(B, i); |
||||
Error += glm::equal(A, C, 0) ? 0 : 1; |
||||
|
||||
int D = glm::float_distance(A, B); |
||||
Error += D == i ? 0 : 1; |
||||
int E = glm::float_distance(A, C); |
||||
Error += E == 0 ? 0 : 1; |
||||
} |
||||
|
||||
return Error; |
||||
} |
||||
|
||||
static int test_ulp_double_dist() |
||||
{ |
||||
int Error = 0; |
||||
|
||||
double A = 1.0; |
||||
|
||||
double B = glm::next_float(A); |
||||
Error += glm::notEqual(A, B, 0) ? 0 : 1; |
||||
double C = glm::prev_float(B); |
||||
Error += glm::equal(A, C, 0) ? 0 : 1; |
||||
|
||||
glm::int64 const D = glm::float_distance(A, B); |
||||
Error += D == 1 ? 0 : 1; |
||||
glm::int64 const E = glm::float_distance(A, C); |
||||
Error += E == 0 ? 0 : 1; |
||||
|
||||
return Error; |
||||
} |
||||
|
||||
static int test_ulp_double_step() |
||||
{ |
||||
int Error = 0; |
||||
|
||||
double A = 1.0; |
||||
|
||||
for(int i = 10; i < 1000; i *= 10) |
||||
{ |
||||
double B = glm::next_float(A, i); |
||||
Error += glm::notEqual(A, B, 0) ? 0 : 1; |
||||
double C = glm::prev_float(B, i); |
||||
Error += glm::equal(A, C, 0) ? 0 : 1; |
||||
|
||||
glm::int64 const D = glm::float_distance(A, B); |
||||
Error += D == i ? 0 : 1; |
||||
glm::int64 const E = glm::float_distance(A, C); |
||||
Error += E == 0 ? 0 : 1; |
||||
} |
||||
|
||||
return Error; |
||||
} |
||||
|
||||
int main() |
||||
{ |
||||
int Error = 0; |
||||
|
||||
Error += test_ulp_float_dist(); |
||||
Error += test_ulp_float_step(); |
||||
Error += test_ulp_double_dist(); |
||||
Error += test_ulp_double_step(); |
||||
|
||||
return Error; |
||||
} |
@ -0,0 +1,99 @@ |
||||
#include <glm/ext/vector_ulp.hpp> |
||||
#include <glm/ext/vector_relational.hpp> |
||||
#include <glm/ext/vector_float4.hpp> |
||||
#include <glm/ext/vector_double4.hpp> |
||||
#include <glm/ext/vector_int4.hpp> |
||||
|
||||
static int test_ulp_float_dist() |
||||
{ |
||||
int Error = 0; |
||||
|
||||
glm::vec4 const A(1.0f); |
||||
|
||||
glm::vec4 const B = glm::next_float(A); |
||||
Error += glm::any(glm::notEqual(A, B, 0)) ? 0 : 1; |
||||
glm::vec4 const C = glm::prev_float(B); |
||||
Error += glm::all(glm::equal(A, C, 0)) ? 0 : 1; |
||||
|
||||
glm::ivec4 const D = glm::float_distance(A, B); |
||||
Error += D == glm::ivec4(1) ? 0 : 1; |
||||
glm::ivec4 const E = glm::float_distance(A, C); |
||||
Error += E == glm::ivec4(0) ? 0 : 1; |
||||
|
||||
return Error; |
||||
} |
||||
|
||||
static int test_ulp_float_step() |
||||
{ |
||||
int Error = 0; |
||||
|
||||
glm::vec4 const A(1.0f); |
||||
|
||||
for(int i = 10; i < 1000; i *= 10) |
||||
{ |
||||
glm::vec4 const B = glm::next_float(A, i); |
||||
Error += glm::any(glm::notEqual(A, B, 0)) ? 0 : 1; |
||||
glm::vec4 const C = glm::prev_float(B, i); |
||||
Error += glm::all(glm::equal(A, C, 0)) ? 0 : 1; |
||||
|
||||
glm::ivec4 const D = glm::float_distance(A, B); |
||||
Error += D == glm::ivec4(i) ? 0 : 1; |
||||
glm::ivec4 const E = glm::float_distance(A, C); |
||||
Error += E == glm::ivec4(0) ? 0 : 1; |
||||
} |
||||
|
||||
return Error; |
||||
} |
||||
|
||||
static int test_ulp_double_dist() |
||||
{ |
||||
int Error = 0; |
||||
|
||||
glm::dvec4 const A(1.0); |
||||
|
||||
glm::dvec4 const B = glm::next_float(A); |
||||
Error += glm::any(glm::notEqual(A, B, 0)) ? 0 : 1; |
||||
glm::dvec4 const C = glm::prev_float(B); |
||||
Error += glm::all(glm::equal(A, C, 0)) ? 0 : 1; |
||||
|
||||
glm::ivec4 const D(glm::float_distance(A, B)); |
||||
Error += D == glm::ivec4(1) ? 0 : 1; |
||||
glm::ivec4 const E = glm::float_distance(A, C); |
||||
Error += E == glm::ivec4(0) ? 0 : 1; |
||||
|
||||
return Error; |
||||
} |
||||
|
||||
static int test_ulp_double_step() |
||||
{ |
||||
int Error = 0; |
||||
|
||||
glm::dvec4 const A(1.0); |
||||
|
||||
for(int i = 10; i < 1000; i *= 10) |
||||
{ |
||||
glm::dvec4 const B = glm::next_float(A, i); |
||||
Error += glm::any(glm::notEqual(A, B, 0)) ? 0 : 1; |
||||
glm::dvec4 const C = glm::prev_float(B, i); |
||||
Error += glm::all(glm::equal(A, C, 0)) ? 0 : 1; |
||||
|
||||
glm::ivec4 const D(glm::float_distance(A, B)); |
||||
Error += D == glm::ivec4(i) ? 0 : 1; |
||||
glm::ivec4 const E(glm::float_distance(A, C)); |
||||
Error += E == glm::ivec4(0) ? 0 : 1; |
||||
} |
||||
|
||||
return Error; |
||||
} |
||||
|
||||
int main() |
||||
{ |
||||
int Error = 0; |
||||
|
||||
Error += test_ulp_float_dist(); |
||||
Error += test_ulp_float_step(); |
||||
Error += test_ulp_double_dist(); |
||||
Error += test_ulp_double_step(); |
||||
|
||||
return Error; |
||||
} |
Loading…
Reference in New Issue