Fixed mathlib unit tests

Added popcnt support check
Removed integer division optimization from asmlib.h
Fixed typo in VectorCompare
This commit is contained in:
asmodai 2016-02-06 03:41:32 +03:00
parent 6c01cf7817
commit 0d6a95093f
5 changed files with 54 additions and 193 deletions

View File

@ -340,10 +340,6 @@ void AngleVectors(const vec_t *angles, vec_t *forward, vec_t *right, vec_t *up)
// parallel SSE version
void AngleVectorsTranspose(const vec_t *angles, vec_t *forward, vec_t *right, vec_t *up)
{
#ifndef SWDS
g_engdstAddrs.pfnAngleVectors(&angles, &forward, &right, &up);
#endif // SWDS
__m128 s, c;
sincos_ps(_mm_mul_ps(_mm_loadu_ps(angles), _mm_load_ps(deg2rad)), &s, &c);
@ -425,10 +421,6 @@ void AngleVectorsTranspose(const vec_t *angles, vec_t *forward, vec_t *right, ve
// parallel SSE version
void AngleMatrix(const vec_t *angles, float(*matrix)[4])
{
#ifndef SWDS
g_engdstAddrs.pfnAngleVectors(&angles, &forward, &right, &up);
#endif // SWDS
__m128 s, c;
sincos_ps(_mm_mul_ps(_mm_loadu_ps(angles), _mm_load_ps(deg2rad)), &s, &c);
@ -547,31 +539,27 @@ NOBODY void InterpolateAngles(float *start, float *end, float *output, float fra
//}
/* <47495> ../engine/mathlib.c:457 */
//#ifndef REHLDS_FIXES
//#else
void VectorTransform(const vec_t *in1, float *in2, vec_t *out)
{
out[0] = _DotProduct(in1, in2 + 0) + in2[3];
out[1] = _DotProduct(in1, in2 + 4) + in2[7];
out[2] = _DotProduct(in1, in2 + 8) + in2[11];
}
//#endif
/* <474dc> ../engine/mathlib.c:465 */
int VectorCompare(const vec_t *v1, const vec_t *v2)
{
#ifdef REHLDS_FIXES
__m128 cmp = _mm_cmpneq_ss(_mm_loadu_ps(v1), _mm_loadu_ps(v2));
return !(_mm_movemask_epi8(*(__m128i *)&cmp) & 0xFFFFFF);
#else
#ifdef REHLDS_OPT_PEDANTIC
__m128 cmp = _mm_cmpneq_ps(_mm_loadu_ps(v1), _mm_loadu_ps(v2));
return !(_mm_movemask_epi8(*(__m128i *)&cmp) & 0xFFF);
#else // REHLDS_OPT_PEDANTIC
for (int i = 0; i < 3; i++)
{
if (v1[i] != v2[i]) return 0;
}
return 1;
#endif
#endif // REHLDS_OPT_PEDANTIC
}
#ifdef REHLDS_FIXES
@ -775,7 +763,7 @@ NOBODY void R_ConcatRotations(float *in1, float *in2, float *out);
/* <47a04> ../engine/mathlib.c:660 */
#ifdef REHLDS_FIXES
void NOINLINE R_ConcatTransforms(float in1[3][4], float in2[3][4], float out[3][4])
void R_ConcatTransforms(float in1[3][4], float in2[3][4], float out[3][4])
{
for (size_t i = 0; i < 3; i++)
{

View File

@ -120,105 +120,4 @@ static inline const char * A_strstr(const char * haystack, const char * needle)
#endif // __cplusplus
/***********************************************************************
Function prototypes, integer division functions
***********************************************************************/
// Turn off name mangling
#ifdef __cplusplus
extern "C" {
#endif
void setdivisori32(int buffer[2], int d); // Set divisor for repeated division
int dividefixedi32(const int buffer[2], int x); // Fast division with previously set divisor
void setdivisoru32(uint32_t buffer[2], uint32_t d); // Set divisor for repeated division
uint32_t dividefixedu32(const uint32_t buffer[2], uint32_t x); // Fast division with previously set divisor
// Test if emmintrin.h is included and __m128i defined
#if defined(__GNUC__) && defined(_EMMINTRIN_H_INCLUDED) && !defined(__SSE2__)
#error Please compile with -sse2 or higher
#endif
#if defined(_INCLUDED_EMM) || (defined(_EMMINTRIN_H_INCLUDED) && defined(__SSE2__))
#define VECTORDIVISIONDEFINED
// Integer vector division functions. These functions divide an integer vector by a scalar:
// Set divisor for repeated integer vector division
void setdivisorV8i16(__m128i buf[2], int16_t d); // Set divisor for repeated division
void setdivisorV8u16(__m128i buf[2], uint16_t d); // Set divisor for repeated division
void setdivisorV4i32(__m128i buf[2], int32_t d); // Set divisor for repeated division
void setdivisorV4u32(__m128i buf[2], uint32_t d); // Set divisor for repeated division
// Fast division of vector by previously set divisor
__m128i dividefixedV8i16(const __m128i buf[2], __m128i x); // Fast division with previously set divisor
__m128i dividefixedV8u16(const __m128i buf[2], __m128i x); // Fast division with previously set divisor
__m128i dividefixedV4i32(const __m128i buf[2], __m128i x); // Fast division with previously set divisor
__m128i dividefixedV4u32(const __m128i buf[2], __m128i x); // Fast division with previously set divisor
#endif // defined(_INCLUDED_EMM) || (defined(_EMMINTRIN_H_INCLUDED) && defined(__SSE2__))
#ifdef __cplusplus
} // end of extern "C"
#endif // __cplusplus
#ifdef __cplusplus
// Define classes and operator '/' for fast division with fixed divisor
class div_i32;
class div_u32;
static inline int32_t operator / (int32_t x, div_i32 const &D);
static inline uint32_t operator / (uint32_t x, div_u32 const & D);
class div_i32 { // Signed 32 bit integer division
public:
div_i32() { // Default constructor
buffer[0] = buffer[1] = 0;
}
div_i32(int d) { // Constructor with divisor
setdivisor(d);
}
void setdivisor(int d) { // Set divisor
setdivisori32(buffer, d);
}
protected:
int buffer[2]; // Internal memory
friend int32_t operator / (int32_t x, div_i32 const & D);
};
static inline int32_t operator / (int32_t x, div_i32 const &D){// Overloaded operator '/'
return dividefixedi32(D.buffer, x);
}
static inline int32_t operator /= (int32_t &x, div_i32 const &D){// Overloaded operator '/='
return x = x / D;
}
class div_u32 { // Unsigned 32 bit integer division
public:
div_u32() { // Default constructor
buffer[0] = buffer[1] = 0;
}
div_u32(uint32_t d) { // Constructor with divisor
setdivisor(d);
}
void setdivisor(uint32_t d) { // Set divisor
setdivisoru32(buffer, d);
}
protected:
uint32_t buffer[2]; // Internal memory
friend uint32_t operator / (uint32_t x, div_u32 const & D);
};
static inline uint32_t operator / (uint32_t x, div_u32 const & D){ // Overloaded operator '/'
return dividefixedu32(D.buffer, x);
}
static inline uint32_t operator /= (uint32_t &x, div_u32 const &D){// Overloaded operator '/='
return x = x / D;
}
#endif // __cplusplus
#endif // ASMLIB_H

View File

@ -35,6 +35,7 @@
#define SSSE3_FLAG (1<<9)
#define SSE4_1_FLAG (1<<19)
#define SSE4_2_FLAG (1<<20)
#define POPCNT_FLAG (1<<23)
#define AVX_FLAG (1<<28)
#define AVX2_FLAG (1<<5)
@ -56,6 +57,7 @@ void Sys_CheckCpuInstructionsSupport(void)
cpuinfo.ssse3 = (cpuid_data[2] & SSSE3_FLAG) ? 1 : 0;
cpuinfo.sse4_1 = (cpuid_data[2] & SSE4_1_FLAG) ? 1 : 0;
cpuinfo.sse4_2 = (cpuid_data[2] & SSE4_2_FLAG) ? 1 : 0;
cpuinfo.popcnt = (cpuid_data[2] & POPCNT_FLAG) ? 1 : 0;
cpuinfo.avx = (cpuid_data[2] & AVX_FLAG) ? 1 : 0;
#if defined ASMLIB_H

View File

@ -31,7 +31,7 @@
typedef struct cpuinfo_s
{
uint8 sse3, ssse3, sse4_1, sse4_2, avx, avx2;
uint8 sse3, ssse3, sse4_1, sse4_2, avx, avx2, popcnt;
} cpuinfo_t;
extern cpuinfo_t cpuinfo;

View File

@ -4,9 +4,6 @@
#include <iostream>
TEST(AngleVectorsTest, MathLib, 1000) {
Sys_CheckCpuInstructionsSupport();
CHECK_WARNING_OUT("SSE4.1 Support", cpuinfo.sse4_1);
struct testdata_t {
vec3_t angles;
vec3_t forward, right, up;
@ -17,33 +14,26 @@ TEST(AngleVectorsTest, MathLib, 1000) {
{ { 106.0f, 142.0f, 62.0f }, { 0.21721f, -0.16970f, -0.96126f }, { 0.95785f, -0.15259f, 0.24337f }, { 0.18798f, 0.97361f, -0.12940f } }
};
for (int sse = 0; sse <= 1; sse++) {
vec3_t forward, right, up;
vec3_t forward, right, up;
for (int i = 0; i < ARRAYSIZE(testdata); i++) {
AngleVectors(testdata[i].angles, forward, right, up);
for (int i = 0; i < ARRAYSIZE(testdata); i++) {
AngleVectors(testdata[i].angles, forward, right, up);
DOUBLES_EQUAL("forward[0] mismatch", testdata[i].forward[0], forward[0], 0.00001);
DOUBLES_EQUAL("forward[1] mismatch", testdata[i].forward[1], forward[1], 0.00001);
DOUBLES_EQUAL("forward[2] mismatch", testdata[i].forward[2], forward[2], 0.00001);
DOUBLES_EQUAL("forward[0] mismatch", testdata[i].forward[0], forward[0], 0.00001);
DOUBLES_EQUAL("forward[1] mismatch", testdata[i].forward[1], forward[1], 0.00001);
DOUBLES_EQUAL("forward[2] mismatch", testdata[i].forward[2], forward[2], 0.00001);
DOUBLES_EQUAL("right[0] mismatch", testdata[i].right[0], right[0], 0.00001);
DOUBLES_EQUAL("right[1] mismatch", testdata[i].right[1], right[1], 0.00001);
DOUBLES_EQUAL("right[2] mismatch", testdata[i].right[2], right[2], 0.00001);
DOUBLES_EQUAL("right[0] mismatch", testdata[i].right[0], right[0], 0.00001);
DOUBLES_EQUAL("right[1] mismatch", testdata[i].right[1], right[1], 0.00001);
DOUBLES_EQUAL("right[2] mismatch", testdata[i].right[2], right[2], 0.00001);
DOUBLES_EQUAL("up[0] mismatch", testdata[i].up[0], up[0], 0.00001);
DOUBLES_EQUAL("up[1] mismatch", testdata[i].up[1], up[1], 0.00001);
DOUBLES_EQUAL("up[2] mismatch", testdata[i].up[2], up[2], 0.00001);
}
cpuinfo.sse4_1 = 0;
DOUBLES_EQUAL("up[0] mismatch", testdata[i].up[0], up[0], 0.00001);
DOUBLES_EQUAL("up[1] mismatch", testdata[i].up[1], up[1], 0.00001);
DOUBLES_EQUAL("up[2] mismatch", testdata[i].up[2], up[2], 0.00001);
}
}
TEST(AngleVectorsTransposeTest, MathLib, 1000) {
Sys_CheckCpuInstructionsSupport();
CHECK_WARNING_OUT("SSE4.1 Support", cpuinfo.sse4_1);
struct testdata_t {
vec3_t angles;
vec3_t forward, right, up;
@ -54,33 +44,26 @@ TEST(AngleVectorsTransposeTest, MathLib, 1000) {
{ { 106.0f, 142.0f, 62.0f }, { 0.21721f, -0.95785f, 0.18798f }, { -0.16970f, 0.15259f, 0.97361f }, { -0.96126f, -0.24337f, -0.12940f } }
};
for (int sse = 0; sse <= 1; sse++) {
vec3_t forward, right, up;
vec3_t forward, right, up;
for (int i = 0; i < ARRAYSIZE(testdata); i++) {
AngleVectorsTranspose(testdata[i].angles, forward, right, up);
for (int i = 0; i < ARRAYSIZE(testdata); i++) {
AngleVectorsTranspose(testdata[i].angles, forward, right, up);
DOUBLES_EQUAL("forward[0] mismatch", testdata[i].forward[0], forward[0], 0.00001);
DOUBLES_EQUAL("forward[1] mismatch", testdata[i].forward[1], forward[1], 0.00001);
DOUBLES_EQUAL("forward[2] mismatch", testdata[i].forward[2], forward[2], 0.00001);
DOUBLES_EQUAL("forward[0] mismatch", testdata[i].forward[0], forward[0], 0.00001);
DOUBLES_EQUAL("forward[1] mismatch", testdata[i].forward[1], forward[1], 0.00001);
DOUBLES_EQUAL("forward[2] mismatch", testdata[i].forward[2], forward[2], 0.00001);
DOUBLES_EQUAL("right[0] mismatch", testdata[i].right[0], right[0], 0.00001);
DOUBLES_EQUAL("right[1] mismatch", testdata[i].right[1], right[1], 0.00001);
DOUBLES_EQUAL("right[2] mismatch", testdata[i].right[2], right[2], 0.00001);
DOUBLES_EQUAL("right[0] mismatch", testdata[i].right[0], right[0], 0.00001);
DOUBLES_EQUAL("right[1] mismatch", testdata[i].right[1], right[1], 0.00001);
DOUBLES_EQUAL("right[2] mismatch", testdata[i].right[2], right[2], 0.00001);
DOUBLES_EQUAL("up[0] mismatch", testdata[i].up[0], up[0], 0.00001);
DOUBLES_EQUAL("up[1] mismatch", testdata[i].up[1], up[1], 0.00001);
DOUBLES_EQUAL("up[2] mismatch", testdata[i].up[2], up[2], 0.00001);
}
cpuinfo.sse4_1 = 0;
DOUBLES_EQUAL("up[0] mismatch", testdata[i].up[0], up[0], 0.00001);
DOUBLES_EQUAL("up[1] mismatch", testdata[i].up[1], up[1], 0.00001);
DOUBLES_EQUAL("up[2] mismatch", testdata[i].up[2], up[2], 0.00001);
}
}
TEST(AngleMatrixTest, MathLib, 1000) {
Sys_CheckCpuInstructionsSupport();
CHECK_WARNING_OUT("SSE4.1 Support", cpuinfo.sse4_1);
struct testdata_t {
vec3_t angles;
vec_t matrix0[4];
@ -93,29 +76,25 @@ TEST(AngleMatrixTest, MathLib, 1000) {
{ { 106.0f, 142.0f, 62.0f }, { 0.21721f, -0.95785f, 0.18798f, 0.0f }, { -0.16970f, 0.15259f, 0.97361f, 0.0f }, { -0.96126f, -0.24337f, -0.12940f, 0.0f } }
};
for (int sse = 0; sse <= 1; sse++) {
float rotation_matrix[3][4];
float rotation_matrix[3][4];
for (int i = 0; i < ARRAYSIZE(testdata); i++) {
AngleMatrix(testdata[i].angles, rotation_matrix);
for (int i = 0; i < ARRAYSIZE(testdata); i++) {
AngleMatrix(testdata[i].angles, rotation_matrix);
DOUBLES_EQUAL("rotationmatrix[0][0] mismatch", testdata[i].matrix0[0], rotation_matrix[0][0], 0.00001);
DOUBLES_EQUAL("rotationmatrix[0][1] mismatch", testdata[i].matrix0[1], rotation_matrix[0][1], 0.00001);
DOUBLES_EQUAL("rotationmatrix[0][2] mismatch", testdata[i].matrix0[2], rotation_matrix[0][2], 0.00001);
DOUBLES_EQUAL("rotationmatrix[0][3] mismatch", testdata[i].matrix0[3], rotation_matrix[0][3], 0.00001);
DOUBLES_EQUAL("rotationmatrix[0][0] mismatch", testdata[i].matrix0[0], rotation_matrix[0][0], 0.00001);
DOUBLES_EQUAL("rotationmatrix[0][1] mismatch", testdata[i].matrix0[1], rotation_matrix[0][1], 0.00001);
DOUBLES_EQUAL("rotationmatrix[0][2] mismatch", testdata[i].matrix0[2], rotation_matrix[0][2], 0.00001);
DOUBLES_EQUAL("rotationmatrix[0][3] mismatch", testdata[i].matrix0[3], rotation_matrix[0][3], 0.00001);
DOUBLES_EQUAL("rotationmatrix[1][0] mismatch", testdata[i].matrix1[0], rotation_matrix[1][0], 0.00001);
DOUBLES_EQUAL("rotationmatrix[1][1] mismatch", testdata[i].matrix1[1], rotation_matrix[1][1], 0.00001);
DOUBLES_EQUAL("rotationmatrix[1][2] mismatch", testdata[i].matrix1[2], rotation_matrix[1][2], 0.00001);
DOUBLES_EQUAL("rotationmatrix[1][3] mismatch", testdata[i].matrix1[3], rotation_matrix[1][3], 0.00001);
DOUBLES_EQUAL("rotationmatrix[1][0] mismatch", testdata[i].matrix1[0], rotation_matrix[1][0], 0.00001);
DOUBLES_EQUAL("rotationmatrix[1][1] mismatch", testdata[i].matrix1[1], rotation_matrix[1][1], 0.00001);
DOUBLES_EQUAL("rotationmatrix[1][2] mismatch", testdata[i].matrix1[2], rotation_matrix[1][2], 0.00001);
DOUBLES_EQUAL("rotationmatrix[1][3] mismatch", testdata[i].matrix1[3], rotation_matrix[1][3], 0.00001);
DOUBLES_EQUAL("rotationmatrix[2][0] mismatch", testdata[i].matrix2[0], rotation_matrix[2][0], 0.00001);
DOUBLES_EQUAL("rotationmatrix[2][1] mismatch", testdata[i].matrix2[1], rotation_matrix[2][1], 0.00001);
DOUBLES_EQUAL("rotationmatrix[2][2] mismatch", testdata[i].matrix2[2], rotation_matrix[2][2], 0.00001);
DOUBLES_EQUAL("rotationmatrix[2][3] mismatch", testdata[i].matrix2[3], rotation_matrix[2][3], 0.00001);
}
cpuinfo.sse4_1 = 0;
DOUBLES_EQUAL("rotationmatrix[2][0] mismatch", testdata[i].matrix2[0], rotation_matrix[2][0], 0.00001);
DOUBLES_EQUAL("rotationmatrix[2][1] mismatch", testdata[i].matrix2[1], rotation_matrix[2][1], 0.00001);
DOUBLES_EQUAL("rotationmatrix[2][2] mismatch", testdata[i].matrix2[2], rotation_matrix[2][2], 0.00001);
DOUBLES_EQUAL("rotationmatrix[2][3] mismatch", testdata[i].matrix2[3], rotation_matrix[2][3], 0.00001);
}
}
@ -146,9 +125,6 @@ TEST(DotProductTest, MathLib, 1000) {
}
TEST(CrossProductTest, MathLib, 1000) {
Sys_CheckCpuInstructionsSupport();
CHECK_WARNING_OUT("SSE4.1 Support", cpuinfo.sse4_1);
struct testdata_t {
vec3_t v1;
vec3_t v2;
@ -160,18 +136,14 @@ TEST(CrossProductTest, MathLib, 1000) {
{ { -16.1f, -0.09f, 1.2f }, { 8.2f, 1.2f, -6.66f }, { -0.84060f, -97.38600f, -18.58200f } },
};
for (int sse = 0; sse <= 1; sse++) {
vec3_t res;
vec3_t res;
for (int i = 0; i < ARRAYSIZE(testdata); i++) {
CrossProduct(testdata[i].v1, testdata[i].v2, res);
for (int i = 0; i < ARRAYSIZE(testdata); i++) {
CrossProduct(testdata[i].v1, testdata[i].v2, res);
DOUBLES_EQUAL("CrossProduct[0] mismatch", testdata[i].res[0], res[0], 0.00001);
DOUBLES_EQUAL("CrossProduct[1] mismatch", testdata[i].res[1], res[1], 0.00001);
DOUBLES_EQUAL("CrossProduct[2] mismatch", testdata[i].res[2], res[2], 0.00001);
}
cpuinfo.sse4_1 = 0;
DOUBLES_EQUAL("CrossProduct[0] mismatch", testdata[i].res[0], res[0], 0.00001);
DOUBLES_EQUAL("CrossProduct[1] mismatch", testdata[i].res[1], res[1], 0.00001);
DOUBLES_EQUAL("CrossProduct[2] mismatch", testdata[i].res[2], res[2], 0.00001);
}
}