2011-12-05 20:49:37 +00:00
|
|
|
/*
|
|
|
|
* Copyright 2011 Google Inc.
|
|
|
|
*
|
|
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
|
|
* found in the LICENSE file.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "Test.h"
|
|
|
|
#include "SkFloatingPoint.h"
|
|
|
|
#include "SkMath.h"
|
|
|
|
#include "SkPoint.h"
|
|
|
|
#include "SkRandom.h"
|
|
|
|
|
|
|
|
#ifdef SK_CAN_USE_FLOAT
|
|
|
|
|
|
|
|
static bool isFinite_int(float x) {
|
|
|
|
uint32_t bits = SkFloat2Bits(x); // need unsigned for our shifts
|
|
|
|
int exponent = bits << 1 >> 24;
|
|
|
|
return exponent != 0xFF;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool isFinite_float(float x) {
|
2011-12-05 21:47:25 +00:00
|
|
|
return sk_float_isfinite(x);
|
2011-12-05 20:49:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static bool isFinite_mulzero(float x) {
|
|
|
|
float y = x * 0;
|
|
|
|
return y == y;
|
|
|
|
}
|
|
|
|
|
|
|
|
// return true if the float is finite
|
|
|
|
typedef bool (*IsFiniteProc1)(float);
|
|
|
|
|
|
|
|
static bool isFinite2_and(float x, float y, IsFiniteProc1 proc) {
|
|
|
|
return proc(x) && proc(y);
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool isFinite2_mulzeroadd(float x, float y, IsFiniteProc1 proc) {
|
|
|
|
return proc(x * 0 + y * 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
// return true if both floats are finite
|
|
|
|
typedef bool (*IsFiniteProc2)(float, float, IsFiniteProc1);
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2011-12-06 20:18:05 +00:00
|
|
|
enum FloatClass {
|
|
|
|
kFinite,
|
|
|
|
kInfinite,
|
|
|
|
kNaN
|
|
|
|
};
|
|
|
|
|
|
|
|
static void test_floatclass(skiatest::Reporter* reporter, float value, FloatClass fc) {
|
|
|
|
// our sk_float_is... function may return int instead of bool,
|
|
|
|
// hence the double ! to turn it into a bool
|
|
|
|
REPORTER_ASSERT(reporter, !!sk_float_isfinite(value) == (fc == kFinite));
|
|
|
|
REPORTER_ASSERT(reporter, !!sk_float_isinf(value) == (fc == kInfinite));
|
|
|
|
REPORTER_ASSERT(reporter, !!sk_float_isnan(value) == (fc == kNaN));
|
|
|
|
}
|
|
|
|
|
2011-12-05 20:49:37 +00:00
|
|
|
static void test_isfinite(skiatest::Reporter* reporter) {
|
|
|
|
#ifdef SK_CAN_USE_FLOAT
|
|
|
|
struct Rec {
|
|
|
|
float fValue;
|
|
|
|
bool fIsFinite;
|
|
|
|
};
|
|
|
|
|
|
|
|
float max = 3.402823466e+38f;
|
|
|
|
float inf = max * max;
|
2011-12-06 20:18:05 +00:00
|
|
|
float nan = inf * 0;
|
|
|
|
|
|
|
|
test_floatclass(reporter, 0, kFinite);
|
|
|
|
test_floatclass(reporter, max, kFinite);
|
|
|
|
test_floatclass(reporter, -max, kFinite);
|
|
|
|
test_floatclass(reporter, inf, kInfinite);
|
|
|
|
test_floatclass(reporter, -inf, kInfinite);
|
|
|
|
test_floatclass(reporter, nan, kNaN);
|
|
|
|
test_floatclass(reporter, -nan, kNaN);
|
2011-12-05 20:49:37 +00:00
|
|
|
|
|
|
|
const Rec data[] = {
|
|
|
|
{ 0, true },
|
|
|
|
{ 1, true },
|
|
|
|
{ -1, true },
|
|
|
|
{ max * 0.75, true },
|
|
|
|
{ max, true },
|
|
|
|
{ -max * 0.75, true },
|
|
|
|
{ -max, true },
|
|
|
|
{ inf, false },
|
|
|
|
{ -inf, false },
|
|
|
|
{ nan, false },
|
|
|
|
};
|
|
|
|
|
|
|
|
const IsFiniteProc1 gProc1[] = {
|
|
|
|
isFinite_int,
|
|
|
|
isFinite_float,
|
|
|
|
isFinite_mulzero
|
|
|
|
};
|
|
|
|
const IsFiniteProc2 gProc2[] = {
|
|
|
|
isFinite2_and,
|
|
|
|
isFinite2_mulzeroadd
|
|
|
|
};
|
|
|
|
|
2012-01-06 19:22:11 +00:00
|
|
|
size_t i, n = SK_ARRAY_COUNT(data);
|
2011-12-05 20:49:37 +00:00
|
|
|
|
|
|
|
for (i = 0; i < n; ++i) {
|
2012-01-06 19:22:11 +00:00
|
|
|
for (size_t k = 0; k < SK_ARRAY_COUNT(gProc1); ++k) {
|
2011-12-05 20:49:37 +00:00
|
|
|
const Rec& rec = data[i];
|
|
|
|
bool finite = gProc1[k](rec.fValue);
|
|
|
|
REPORTER_ASSERT(reporter, rec.fIsFinite == finite);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < n; ++i) {
|
|
|
|
const Rec& rec0 = data[i];
|
2012-01-06 19:22:11 +00:00
|
|
|
for (size_t j = 0; j < n; ++j) {
|
2011-12-05 20:49:37 +00:00
|
|
|
const Rec& rec1 = data[j];
|
2012-01-06 19:22:11 +00:00
|
|
|
for (size_t k = 0; k < SK_ARRAY_COUNT(gProc1); ++k) {
|
2011-12-05 20:49:37 +00:00
|
|
|
IsFiniteProc1 proc1 = gProc1[k];
|
|
|
|
|
2012-01-06 19:22:11 +00:00
|
|
|
for (size_t m = 0; m < SK_ARRAY_COUNT(gProc2); ++m) {
|
2011-12-05 20:49:37 +00:00
|
|
|
bool finite = gProc2[m](rec0.fValue, rec1.fValue, proc1);
|
|
|
|
bool finite2 = rec0.fIsFinite && rec1.fIsFinite;
|
|
|
|
REPORTER_ASSERT(reporter, finite2 == finite);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
static void TestScalar(skiatest::Reporter* reporter) {
|
|
|
|
test_isfinite(reporter);
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "TestClassDef.h"
|
|
|
|
DEFINE_TESTCLASS("Scalar", TestScalarClass, TestScalar)
|
|
|
|
|