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 
     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