1 /* 2 * Copyright 2011 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #include "Test.h" 9 #include "SkFloatingPoint.h" 10 #include "SkMath.h" 11 #include "SkPoint.h" 12 #include "SkRandom.h" 13 14 #ifdef SK_CAN_USE_FLOAT 15 16 static bool isFinite_int(float x) { 17 uint32_t bits = SkFloat2Bits(x); // need unsigned for our shifts 18 int exponent = bits << 1 >> 24; 19 return exponent != 0xFF; 20 } 21 22 static bool isFinite_float(float x) { 23 return sk_float_isfinite(x); 24 } 25 26 static bool isFinite_mulzero(float x) { 27 float y = x * 0; 28 return y == y; 29 } 30 31 // return true if the float is finite 32 typedef bool (*IsFiniteProc1)(float); 33 34 static bool isFinite2_and(float x, float y, IsFiniteProc1 proc) { 35 return proc(x) && proc(y); 36 } 37 38 static bool isFinite2_mulzeroadd(float x, float y, IsFiniteProc1 proc) { 39 return proc(x * 0 + y * 0); 40 } 41 42 // return true if both floats are finite 43 typedef bool (*IsFiniteProc2)(float, float, IsFiniteProc1); 44 45 #endif 46 47 enum FloatClass { 48 kFinite, 49 kInfinite, 50 kNaN 51 }; 52 53 static void test_floatclass(skiatest::Reporter* reporter, float value, FloatClass fc) { 54 // our sk_float_is... function may return int instead of bool, 55 // hence the double ! to turn it into a bool 56 REPORTER_ASSERT(reporter, !!sk_float_isfinite(value) == (fc == kFinite)); 57 REPORTER_ASSERT(reporter, !!sk_float_isinf(value) == (fc == kInfinite)); 58 REPORTER_ASSERT(reporter, !!sk_float_isnan(value) == (fc == kNaN)); 59 } 60 61 static void test_isfinite(skiatest::Reporter* reporter) { 62 #ifdef SK_CAN_USE_FLOAT 63 struct Rec { 64 float fValue; 65 bool fIsFinite; 66 }; 67 68 float max = 3.402823466e+38f; 69 float inf = max * max; 70 float nan = inf * 0; 71 72 test_floatclass(reporter, 0, kFinite); 73 test_floatclass(reporter, max, kFinite); 74 test_floatclass(reporter, -max, kFinite); 75 test_floatclass(reporter, inf, kInfinite); 76 test_floatclass(reporter, -inf, kInfinite); 77 test_floatclass(reporter, nan, kNaN); 78 test_floatclass(reporter, -nan, kNaN); 79 80 const Rec data[] = { 81 { 0, true }, 82 { 1, true }, 83 { -1, true }, 84 { max * 0.75, true }, 85 { max, true }, 86 { -max * 0.75, true }, 87 { -max, true }, 88 { inf, false }, 89 { -inf, false }, 90 { nan, false }, 91 }; 92 93 const IsFiniteProc1 gProc1[] = { 94 isFinite_int, 95 isFinite_float, 96 isFinite_mulzero 97 }; 98 const IsFiniteProc2 gProc2[] = { 99 isFinite2_and, 100 isFinite2_mulzeroadd 101 }; 102 103 size_t i, n = SK_ARRAY_COUNT(data); 104 105 for (i = 0; i < n; ++i) { 106 for (size_t k = 0; k < SK_ARRAY_COUNT(gProc1); ++k) { 107 const Rec& rec = data[i]; 108 bool finite = gProc1[k](rec.fValue); 109 REPORTER_ASSERT(reporter, rec.fIsFinite == finite); 110 } 111 } 112 113 for (i = 0; i < n; ++i) { 114 const Rec& rec0 = data[i]; 115 for (size_t j = 0; j < n; ++j) { 116 const Rec& rec1 = data[j]; 117 for (size_t k = 0; k < SK_ARRAY_COUNT(gProc1); ++k) { 118 IsFiniteProc1 proc1 = gProc1[k]; 119 120 for (size_t m = 0; m < SK_ARRAY_COUNT(gProc2); ++m) { 121 bool finite = gProc2[m](rec0.fValue, rec1.fValue, proc1); 122 bool finite2 = rec0.fIsFinite && rec1.fIsFinite; 123 REPORTER_ASSERT(reporter, finite2 == finite); 124 } 125 } 126 } 127 } 128 #endif 129 } 130 131 static void TestScalar(skiatest::Reporter* reporter) { 132 test_isfinite(reporter); 133 } 134 135 #include "TestClassDef.h" 136 DEFINE_TESTCLASS("Scalar", TestScalarClass, TestScalar) 137 138