Skip to content

Commit

Permalink
shader_test: more Float tests (2)
Browse files Browse the repository at this point in the history
  • Loading branch information
valdok committed Jul 11, 2024
1 parent fd92382 commit 48108b4
Show file tree
Hide file tree
Showing 2 changed files with 130 additions and 9 deletions.
26 changes: 26 additions & 0 deletions bvm/Shaders/Math.h
Original file line number Diff line number Diff line change
Expand Up @@ -1101,6 +1101,14 @@ namespace MultiPrecision
return *this = *this / b;
}

Float& operator <<= (int32_t n) {
return *this = *this << n;
}

Float& operator >>= (int32_t n) {
return *this = *this >> n;
}

int cmp(const Float& x) const
{
if (IsZero())
Expand Down Expand Up @@ -1589,6 +1597,16 @@ namespace MultiPrecision
return IsNumberNnz() && !HaveHiBit();
}

uint64_t get_Num() const
{
return IsNumberNnz() ? get_WithHiBit() : 0;
}

int32_t get_Order() const
{
return m_Order;
}

void Set0() { m_Order = s_Zero; }
void SetNaN() { m_Order = s_NaN; }

Expand Down Expand Up @@ -1837,6 +1855,14 @@ namespace MultiPrecision
return *this = *this / b;
}

FloatEx& operator <<= (int32_t n) {
return *this = *this << n;
}

FloatEx& operator >>= (int32_t n) {
return *this = *this >> n;
}

int cmp(const FloatEx& x) const
{
// negative, zero, positive, NaN
Expand Down
113 changes: 104 additions & 9 deletions bvm/unittest/shaders_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1248,6 +1248,51 @@ namespace bvm2 {
return res * 1e-8;
}

static double ToDouble(Shaders::MultiPrecision::Float x)
{
if (x.IsZero())
return 0;

return ldexp(x.m_Num, x.m_Order);
}

static double ToDouble(Shaders::MultiPrecision::FloatEx x)
{
if (x.IsZero())
return 0;
if (x.IsNaN())
return NAN;

//x.get_0

auto num = (double) x.get_Num();
if (x.IsNegative())
num = -num;
return ldexp(num, x.get_Order() - 63);
}

static void AssertDoubleRelEqual(double a, double b)
{
if (a == 0.)
{
verify_test(b == 0.);
}
else
{
verify_test(isnormal(a) && isnormal(b));

a /= b;
verify_test(isnormal(a));

// double floating-point mantissa is 52 bits, our implementation has 63 bits
// we should have at least 50 bits of precision
const double eps = ldexp(1, -50);

verify_test(a >= 1. - eps);
verify_test(a <= 1. + eps);
}
}

struct NephriteContext
{
MyProcessor& m_Proc;
Expand Down Expand Up @@ -1480,15 +1525,6 @@ namespace bvm2 {
res.m_Data[wlk.m_pKey->m_KeyInContract.m_iEpoch] = *wlk.m_pVal;
}


static double ToDouble(Shaders::Nephrite::Float x)
{
if (x.IsZero())
return 0;

return ldexp(x.m_Num, x.m_Order);
}

struct Entry :public Shaders::Nephrite::Trove
{
Entry()
Expand Down Expand Up @@ -2870,6 +2906,65 @@ namespace bvm2 {
verify_test(RunGuarded_T(cid, args2.s_iMethod, args2));
verify_test(args2.m_Arg1.RoundDown(d));
verify_test(d == -static_cast<int64_t>(a + b));


// Multiplication

args2.m_Arg1 = a;
args2.m_Arg2 = b;
args2.m_Op = 2; // mul
args2.m_Arg1 <<= 70;
args2.m_Arg2 >>= 300;

double a_ = ToDouble(args2.m_Arg1);
double b_ = ToDouble(args2.m_Arg2);
double c_ = a_ * b_;

verify_test(RunGuarded_T(cid, args2.s_iMethod, args2));
double d_ = ToDouble(args2.m_Arg1);

AssertDoubleRelEqual(c_, d_);

args2.m_Arg1 = a;
args2.m_Arg1 <<= 705;
args2.m_Arg1.Negate();

a_ = ToDouble(args2.m_Arg1);
c_ = a_ * b_;

verify_test(RunGuarded_T(cid, args2.s_iMethod, args2));
d_ = ToDouble(args2.m_Arg1);

AssertDoubleRelEqual(c_, d_);

// Division
args2.m_Arg1 = a;
args2.m_Arg1 <<= 75;
args2.m_Arg2.Negate();
args2.m_Op = 3; // div

a_ = ToDouble(args2.m_Arg1);
b_ = ToDouble(args2.m_Arg2);

verify_test(RunGuarded_T(cid, args2.s_iMethod, args2));

if (b)
{
c_ = a_ / b_;
d_ = ToDouble(args2.m_Arg1);
AssertDoubleRelEqual(c_, d_);
}
else
verify_test(args2.m_Arg1.IsNaN());

args2.m_Arg1 = 0;
verify_test(RunGuarded_T(cid, args2.s_iMethod, args2));

if (b)
verify_test(args2.m_Arg1.IsZero());
else
verify_test(args2.m_Arg1.IsNaN());

}
}

Expand Down

0 comments on commit 48108b4

Please sign in to comment.