Skip to content

Commit

Permalink
Let's see if we can do without the special checks in double precision.
Browse files Browse the repository at this point in the history
  • Loading branch information
hrydgard committed Oct 10, 2020
1 parent e92bfcd commit 512dbd3
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 1 deletion.
8 changes: 8 additions & 0 deletions Core/MIPS/MIPSVFPUUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,21 @@ inline int Xpose(int v) {
return v^0x20;
}

// Half of PI, or 90 degrees.
#ifndef M_PI_2
#define M_PI_2 1.57079632679489661923
#endif

// The VFPU uses weird angles where 4.0 represents a full circle. This makes it possible to return
// exact 1.0/-1.0 values at certain angles.

// Some games depend on exact values, but sinf() and cosf() aren't always precise.
// Stepping down to [0, 2pi) helps, but we also check common exact-result values.
// TODO: cos(1) and sin(2) should be -0.0, but doing that gives wrong results (possibly from floorf.)
// Messing around with the modulo functions? try https://www.desmos.com/calculator.
inline float vfpu_sin(float angle_f) {
double angle = angle_f;
/*
angle -= floor(angle * 0.25) * 4.;
if (angle == 0.0f || angle == 2.0) {
return 0.0f;
Expand All @@ -47,12 +52,14 @@ inline float vfpu_sin(float angle_f) {
} else if (angle == 3.0f) {
return -1.0f;
}
*/
angle *= M_PI_2;
return (float)sin(angle);
}

inline float vfpu_cos(float angle_f) {
double angle = angle_f;
/*
angle -= floor(angle * 0.25) * 4.;
if (angle == 1.0 || angle == 3.0) {
return 0.0f;
Expand All @@ -61,6 +68,7 @@ inline float vfpu_cos(float angle_f) {
} else if (angle == 2.0) {
return -1.0f;
}
*/
angle *= (float)M_PI_2;
return (float)cos(angle);
}
Expand Down
14 changes: 13 additions & 1 deletion unittest/UnitTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@
//
// TODO: Make a test of nice unittest asserts and count successes etc.
// Or just integrate with an existing testing framework.
//
// To use, set command line parameter to one or more of the tests below, or "all".
// Search for "availableTests".

#include <cstdio>
#include <cstdlib>
Expand Down Expand Up @@ -308,10 +311,19 @@ bool TestVFPUSinCos() {
EXPECT_APPROX_EQ_FLOAT(sine, 1.0f);
EXPECT_APPROX_EQ_FLOAT(cosine, 0.0f);

for (float angle = -10.0f; angle < 10.0f; angle++) {
vfpu_sincos(-1.0f, sine, cosine);
EXPECT_EQ_FLOAT(sine, -1.0f);
EXPECT_EQ_FLOAT(cosine, 0.0f);
vfpu_sincos(-2.0f, sine, cosine);
EXPECT_EQ_FLOAT(sine, 0.0f);
EXPECT_EQ_FLOAT(cosine, -1.0f);

for (float angle = -10.0f; angle < 10.0f; angle += 0.1f) {
vfpu_sincos(angle, sine, cosine);
EXPECT_APPROX_EQ_FLOAT(sine, sinf(angle * M_PI_2));
EXPECT_APPROX_EQ_FLOAT(cosine, cosf(angle * M_PI_2));

printf("sine: %f==%f cosine: %f==%f\n", sine, sinf(angle * M_PI_2), cosine, cosf(angle * M_PI_2));
}
return true;
}
Expand Down

0 comments on commit 512dbd3

Please sign in to comment.