rbdlsim/3rdparty/vectorial/spec/spec_helper.h

216 lines
9.1 KiB
C++

#ifndef VECTORIAL_SPEC_HELPER_H
#define VECTORIAL_SPEC_HELPER_H
#define VECTORIAL_OSTREAM
#include "spec.h"
#include "vectorial/vectorial.h"
#ifdef VECTORIAL_HAVE_SIMD2F
#include "vectorial/simd2f.h"
#endif
#include <cmath>
#include <cstdlib>
#include <iostream>
#define should_be_close_to(a,b,tolerance) should_be_close_to_(this, a,b,tolerance,__FILE__,__LINE__)
#define should_be_equal_simd4f( a, b, tolerance) should_be_equal_simd4f_(this, a,b,tolerance,__FILE__,__LINE__)
#define should_be_equal_simd2f( a, b, tolerance) should_be_equal_simd2f_(this, a,b,tolerance,__FILE__,__LINE__)
#define should_be_equal_vec4f( a, b, tolerance) should_be_equal_vec4f_(this, a,b,tolerance,__FILE__,__LINE__)
#define should_be_equal_vec3f( a, b, tolerance) should_be_equal_vec3f_(this, a,b,tolerance,__FILE__,__LINE__)
#define should_be_equal_vec2f( a, b, tolerance) should_be_equal_vec2f_(this, a,b,tolerance,__FILE__,__LINE__)
#define should_be_equal_simd4x4f( a, b, tolerance) should_be_equal_simd4x4f_(this, a,b,tolerance,__FILE__,__LINE__)
#define should_be_equal_mat4f( a, b, tolerance) should_be_equal_mat4f_(this, a,b,tolerance,__FILE__,__LINE__)
// Based on:
// http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
//
static inline bool compare_floats(float A, float B, int maxUlps)
{
// Make sure maxUlps is non-negative and small enough that the
// default NAN won't compare as equal to anything.
// assert(maxUlps > 0 && maxUlps < 4 * 1024 * 1024);
union {
float f;
int i;
} f2iA, f2iB;
f2iA.f = A;
f2iB.f = B;
int aInt = f2iA.i;
// int aInt = *(int*)&A;
// Make aInt lexicographically ordered as a twos-complement int
if (aInt < 0)
aInt = 0x80000000 - aInt;
// Make bInt lexicographically ordered as a twos-complement int
int bInt = f2iB.i;
// int bInt = *(int*)&B;
if (bInt < 0)
bInt = 0x80000000 - bInt;
int intDiff = abs(aInt - bInt);
if (intDiff <= maxUlps)
return true;
return false;
}
static inline void should_be_close_to_(specific::SpecBase *spec, float a, float b, int tolerance, const char *file, int line) {
bool equal=true;
if( !compare_floats(a,b,tolerance) ) equal = false;
std::stringstream ss;
ss << a << " == " << b << " (with tolerance of " << tolerance << ")";
spec->should_test(equal, ss.str().c_str(), file, line);
}
#ifdef VECTORIAL_HAVE_SIMD2F
static inline void should_be_equal_simd2f_(specific::SpecBase *spec, const simd2f& a, const simd2f& b, int tolerance, const char *file, int line) {
bool equal=true;
if( !compare_floats( simd2f_get_x(a), simd2f_get_x(b), tolerance) ) equal = false;
if( !compare_floats( simd2f_get_y(a), simd2f_get_y(b), tolerance) ) equal = false;
std::stringstream ss;
ss << a << " == " << b << " (with tolerance of " << tolerance << ")";
spec->should_test(equal, ss.str().c_str(), file, line);
}
#endif
static inline void should_be_equal_simd4f_(specific::SpecBase *spec, const simd4f& a, const simd4f& b, int tolerance, const char *file, int line) {
bool equal=true;
if( !compare_floats( simd4f_get_x(a), simd4f_get_x(b), tolerance) ) equal = false;
if( !compare_floats( simd4f_get_y(a), simd4f_get_y(b), tolerance) ) equal = false;
if( !compare_floats( simd4f_get_z(a), simd4f_get_z(b), tolerance) ) equal = false;
if( !compare_floats( simd4f_get_w(a), simd4f_get_w(b), tolerance) ) equal = false;
std::stringstream ss;
ss << a << " == " << b << " (with tolerance of " << tolerance << ")";
spec->should_test(equal, ss.str().c_str(), file, line);
}
static inline void should_be_equal_vec4f_(specific::SpecBase *spec, const vectorial::vec4f& a, const vectorial::vec4f& b, int tolerance, const char *file, int line) {
bool equal=true;
if( !compare_floats( a.x(), b.x(), tolerance) ) equal = false;
if( !compare_floats( a.y(), b.y(), tolerance) ) equal = false;
if( !compare_floats( a.z(), b.z(), tolerance) ) equal = false;
if( !compare_floats( a.w(), b.w(), tolerance) ) equal = false;
std::stringstream ss;
ss << a << " == " << b << " (with tolerance of " << tolerance << ")";
spec->should_test(equal, ss.str().c_str(), file, line);
}
static inline void should_be_equal_vec3f_(specific::SpecBase *spec, const vectorial::vec3f& a, const vectorial::vec3f& b, int tolerance, const char *file, int line) {
bool equal=true;
if( !compare_floats( a.x(), b.x(), tolerance) ) equal = false;
if( !compare_floats( a.y(), b.y(), tolerance) ) equal = false;
if( !compare_floats( a.z(), b.z(), tolerance) ) equal = false;
std::stringstream ss;
ss << a << " == " << b << " (with tolerance of " << tolerance << ")";
spec->should_test(equal, ss.str().c_str(), file, line);
}
static inline void should_be_equal_vec2f_(specific::SpecBase *spec, const vectorial::vec2f& a, const vectorial::vec2f& b, int tolerance, const char *file, int line) {
bool equal=true;
if( !compare_floats( a.x(), b.x(), tolerance) ) equal = false;
if( !compare_floats( a.y(), b.y(), tolerance) ) equal = false;
std::stringstream ss;
ss << a << " == " << b << " (with tolerance of " << tolerance << ")";
spec->should_test(equal, ss.str().c_str(), file, line);
}
static inline void should_be_equal_simd4x4f_(specific::SpecBase *spec, const simd4x4f& a, const simd4x4f& b, int tolerance, const char *file, int line) {
bool equal=true;
if( !compare_floats( simd4f_get_x(a.x), simd4f_get_x(b.x), tolerance) ) equal = false;
if( !compare_floats( simd4f_get_y(a.x), simd4f_get_y(b.x), tolerance) ) equal = false;
if( !compare_floats( simd4f_get_z(a.x), simd4f_get_z(b.x), tolerance) ) equal = false;
if( !compare_floats( simd4f_get_w(a.x), simd4f_get_w(b.x), tolerance) ) equal = false;
if( !compare_floats( simd4f_get_x(a.y), simd4f_get_x(b.y), tolerance) ) equal = false;
if( !compare_floats( simd4f_get_y(a.y), simd4f_get_y(b.y), tolerance) ) equal = false;
if( !compare_floats( simd4f_get_z(a.y), simd4f_get_z(b.y), tolerance) ) equal = false;
if( !compare_floats( simd4f_get_w(a.y), simd4f_get_w(b.y), tolerance) ) equal = false;
if( !compare_floats( simd4f_get_x(a.z), simd4f_get_x(b.z), tolerance) ) equal = false;
if( !compare_floats( simd4f_get_y(a.z), simd4f_get_y(b.z), tolerance) ) equal = false;
if( !compare_floats( simd4f_get_z(a.z), simd4f_get_z(b.z), tolerance) ) equal = false;
if( !compare_floats( simd4f_get_w(a.z), simd4f_get_w(b.z), tolerance) ) equal = false;
if( !compare_floats( simd4f_get_x(a.w), simd4f_get_x(b.w), tolerance) ) equal = false;
if( !compare_floats( simd4f_get_y(a.w), simd4f_get_y(b.w), tolerance) ) equal = false;
if( !compare_floats( simd4f_get_z(a.w), simd4f_get_z(b.w), tolerance) ) equal = false;
if( !compare_floats( simd4f_get_w(a.w), simd4f_get_w(b.w), tolerance) ) equal = false;
std::stringstream ss;
ss << a << " == " << b << " (with tolerance of " << tolerance << ")";
spec->should_test(equal, ss.str().c_str(), file, line);
}
static inline void should_be_equal_mat4f_(specific::SpecBase *spec, const vectorial::mat4f& a, const vectorial::mat4f& b, int tolerance, const char *file, int line) {
bool equal=true;
if( !compare_floats( simd4f_get_x(a.value.x), simd4f_get_x(b.value.x), tolerance) ) equal = false;
if( !compare_floats( simd4f_get_y(a.value.x), simd4f_get_y(b.value.x), tolerance) ) equal = false;
if( !compare_floats( simd4f_get_z(a.value.x), simd4f_get_z(b.value.x), tolerance) ) equal = false;
if( !compare_floats( simd4f_get_w(a.value.x), simd4f_get_w(b.value.x), tolerance) ) equal = false;
if( !compare_floats( simd4f_get_x(a.value.y), simd4f_get_x(b.value.y), tolerance) ) equal = false;
if( !compare_floats( simd4f_get_y(a.value.y), simd4f_get_y(b.value.y), tolerance) ) equal = false;
if( !compare_floats( simd4f_get_z(a.value.y), simd4f_get_z(b.value.y), tolerance) ) equal = false;
if( !compare_floats( simd4f_get_w(a.value.y), simd4f_get_w(b.value.y), tolerance) ) equal = false;
if( !compare_floats( simd4f_get_x(a.value.z), simd4f_get_x(b.value.z), tolerance) ) equal = false;
if( !compare_floats( simd4f_get_y(a.value.z), simd4f_get_y(b.value.z), tolerance) ) equal = false;
if( !compare_floats( simd4f_get_z(a.value.z), simd4f_get_z(b.value.z), tolerance) ) equal = false;
if( !compare_floats( simd4f_get_w(a.value.z), simd4f_get_w(b.value.z), tolerance) ) equal = false;
if( !compare_floats( simd4f_get_x(a.value.w), simd4f_get_x(b.value.w), tolerance) ) equal = false;
if( !compare_floats( simd4f_get_y(a.value.w), simd4f_get_y(b.value.w), tolerance) ) equal = false;
if( !compare_floats( simd4f_get_z(a.value.w), simd4f_get_z(b.value.w), tolerance) ) equal = false;
if( !compare_floats( simd4f_get_w(a.value.w), simd4f_get_w(b.value.w), tolerance) ) equal = false;
std::stringstream ss;
ss << a << " == " << b << " (with tolerance of " << tolerance << " ulps)";
spec->should_test(equal, ss.str().c_str(), file, line);
}
#endif