Home | History | Annotate | Download | only in tests
      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 #include "SkRect.h"
     14 
     15 struct PointSet {
     16     const SkPoint* fPts;
     17     size_t         fCount;
     18     bool           fIsFinite;
     19 };
     20 
     21 static void test_isRectFinite(skiatest::Reporter* reporter) {
     22 #ifdef SK_SCALAR_IS_FLOAT
     23     static const SkPoint gF0[] = {
     24         { 0, 0 }, { 1, 1 }
     25     };
     26     static const SkPoint gF1[] = {
     27         { 0, 0 }, { 1, 1 }, { 99.234f, -42342 }
     28     };
     29 
     30     static const SkPoint gI0[] = {
     31         { 0, 0 }, { 1, 1 }, { 99.234f, -42342 }, { SK_ScalarNaN, 3 }, { 2, 3 },
     32     };
     33     static const SkPoint gI1[] = {
     34         { 0, 0 }, { 1, 1 }, { 99.234f, -42342 }, { 3, SK_ScalarNaN }, { 2, 3 },
     35     };
     36     static const SkPoint gI2[] = {
     37         { 0, 0 }, { 1, 1 }, { 99.234f, -42342 }, { SK_ScalarInfinity, 3 }, { 2, 3 },
     38     };
     39     static const SkPoint gI3[] = {
     40         { 0, 0 }, { 1, 1 }, { 99.234f, -42342 }, { 3, SK_ScalarInfinity }, { 2, 3 },
     41     };
     42 
     43     static const struct {
     44         const SkPoint* fPts;
     45         size_t         fCount;
     46         bool           fIsFinite;
     47     } gSets[] = {
     48         { gF0, SK_ARRAY_COUNT(gF0), true },
     49         { gF1, SK_ARRAY_COUNT(gF1), true },
     50 
     51         { gI0, SK_ARRAY_COUNT(gI0), false },
     52         { gI1, SK_ARRAY_COUNT(gI1), false },
     53         { gI2, SK_ARRAY_COUNT(gI2), false },
     54         { gI3, SK_ARRAY_COUNT(gI3), false },
     55     };
     56 
     57     for (size_t i = 0; i < SK_ARRAY_COUNT(gSets); ++i) {
     58         SkRect r;
     59         r.set(gSets[i].fPts, gSets[i].fCount);
     60         bool rectIsFinite = !r.isEmpty();
     61         REPORTER_ASSERT(reporter, gSets[i].fIsFinite == rectIsFinite);
     62     }
     63 #endif
     64 }
     65 
     66 static bool isFinite_int(float x) {
     67     uint32_t bits = SkFloat2Bits(x);    // need unsigned for our shifts
     68     int exponent = bits << 1 >> 24;
     69     return exponent != 0xFF;
     70 }
     71 
     72 static bool isFinite_float(float x) {
     73     return SkToBool(sk_float_isfinite(x));
     74 }
     75 
     76 static bool isFinite_mulzero(float x) {
     77     float y = x * 0;
     78     return y == y;
     79 }
     80 
     81 // return true if the float is finite
     82 typedef bool (*IsFiniteProc1)(float);
     83 
     84 static bool isFinite2_and(float x, float y, IsFiniteProc1 proc) {
     85     return proc(x) && proc(y);
     86 }
     87 
     88 static bool isFinite2_mulzeroadd(float x, float y, IsFiniteProc1 proc) {
     89     return proc(x * 0 + y * 0);
     90 }
     91 
     92 // return true if both floats are finite
     93 typedef bool (*IsFiniteProc2)(float, float, IsFiniteProc1);
     94 
     95 enum FloatClass {
     96     kFinite,
     97     kInfinite,
     98     kNaN
     99 };
    100 
    101 static void test_floatclass(skiatest::Reporter* reporter, float value, FloatClass fc) {
    102     // our sk_float_is... function may return int instead of bool,
    103     // hence the double ! to turn it into a bool
    104     REPORTER_ASSERT(reporter, !!sk_float_isfinite(value) == (fc == kFinite));
    105     REPORTER_ASSERT(reporter, !!sk_float_isinf(value) == (fc == kInfinite));
    106     REPORTER_ASSERT(reporter, !!sk_float_isnan(value) == (fc == kNaN));
    107 }
    108 
    109 #if defined _WIN32
    110 #pragma warning ( push )
    111 // we are intentionally causing an overflow here
    112 //      (warning C4756: overflow in constant arithmetic)
    113 #pragma warning ( disable : 4756 )
    114 #endif
    115 
    116 static void test_isfinite(skiatest::Reporter* reporter) {
    117     struct Rec {
    118         float   fValue;
    119         bool    fIsFinite;
    120     };
    121 
    122     float max = 3.402823466e+38f;
    123     float inf = max * max;
    124     float nan = inf * 0;
    125 
    126     test_floatclass(reporter,    0, kFinite);
    127     test_floatclass(reporter,  max, kFinite);
    128     test_floatclass(reporter, -max, kFinite);
    129     test_floatclass(reporter,  inf, kInfinite);
    130     test_floatclass(reporter, -inf, kInfinite);
    131     test_floatclass(reporter,  nan, kNaN);
    132     test_floatclass(reporter, -nan, kNaN);
    133 
    134     const Rec data[] = {
    135         {   0,           true    },
    136         {   1,           true    },
    137         {  -1,           true    },
    138         {  max * 0.75f,  true    },
    139         {  max,          true    },
    140         {  -max * 0.75f, true    },
    141         {  -max,         true    },
    142         {  inf,          false   },
    143         { -inf,          false   },
    144         {  nan,          false   },
    145     };
    146 
    147     const IsFiniteProc1 gProc1[] = {
    148         isFinite_int,
    149         isFinite_float,
    150         isFinite_mulzero
    151     };
    152     const IsFiniteProc2 gProc2[] = {
    153         isFinite2_and,
    154         isFinite2_mulzeroadd
    155     };
    156 
    157     size_t i, n = SK_ARRAY_COUNT(data);
    158 
    159     for (i = 0; i < n; ++i) {
    160         for (size_t k = 0; k < SK_ARRAY_COUNT(gProc1); ++k) {
    161             const Rec& rec = data[i];
    162             bool finite = gProc1[k](rec.fValue);
    163             REPORTER_ASSERT(reporter, rec.fIsFinite == finite);
    164         }
    165     }
    166 
    167     for (i = 0; i < n; ++i) {
    168         const Rec& rec0 = data[i];
    169         for (size_t j = 0; j < n; ++j) {
    170             const Rec& rec1 = data[j];
    171             for (size_t k = 0; k < SK_ARRAY_COUNT(gProc1); ++k) {
    172                 IsFiniteProc1 proc1 = gProc1[k];
    173 
    174                 for (size_t m = 0; m < SK_ARRAY_COUNT(gProc2); ++m) {
    175                     bool finite = gProc2[m](rec0.fValue, rec1.fValue, proc1);
    176                     bool finite2 = rec0.fIsFinite && rec1.fIsFinite;
    177                     REPORTER_ASSERT(reporter, finite2 == finite);
    178                 }
    179             }
    180         }
    181     }
    182 
    183     test_isRectFinite(reporter);
    184 }
    185 
    186 #if defined _WIN32
    187 #pragma warning ( pop )
    188 #endif
    189 
    190 static void TestScalar(skiatest::Reporter* reporter) {
    191     test_isfinite(reporter);
    192 }
    193 
    194 #include "TestClassDef.h"
    195 DEFINE_TESTCLASS("Scalar", TestScalarClass, TestScalar)
    196