11cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger/*
21cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Copyright 2011 Google Inc.
31cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger *
41cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Use of this source code is governed by a BSD-style license that can be
51cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * found in the LICENSE file.
61cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger */
71cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
81cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#include "Test.h"
91cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#include "SkFloatingPoint.h"
101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#include "SkMath.h"
111cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#include "SkPoint.h"
121cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#include "SkRandom.h"
131cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
141cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#ifdef SK_CAN_USE_FLOAT
151cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic bool isFinite_int(float x) {
171cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    uint32_t bits = SkFloat2Bits(x);    // need unsigned for our shifts
181cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    int exponent = bits << 1 >> 24;
191cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return exponent != 0xFF;
201cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
211cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
221cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic bool isFinite_float(float x) {
231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return sk_float_isfinite(x);
241cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
251cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
261cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic bool isFinite_mulzero(float x) {
271cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    float y = x * 0;
281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return y == y;
291cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
301cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
311cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger// return true if the float is finite
321cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergertypedef bool (*IsFiniteProc1)(float);
331cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
341cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic bool isFinite2_and(float x, float y, IsFiniteProc1 proc) {
351cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return proc(x) && proc(y);
361cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
371cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
381cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic bool isFinite2_mulzeroadd(float x, float y, IsFiniteProc1 proc) {
391cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return proc(x * 0 + y * 0);
401cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
411cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
421cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger// return true if both floats are finite
431cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergertypedef bool (*IsFiniteProc2)(float, float, IsFiniteProc1);
441cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
451cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#endif
461cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
471cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerenum FloatClass {
481cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    kFinite,
491cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    kInfinite,
501cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    kNaN
511cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger};
521cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
531cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic void test_floatclass(skiatest::Reporter* reporter, float value, FloatClass fc) {
541cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // our sk_float_is... function may return int instead of bool,
551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // hence the double ! to turn it into a bool
561cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    REPORTER_ASSERT(reporter, !!sk_float_isfinite(value) == (fc == kFinite));
571cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    REPORTER_ASSERT(reporter, !!sk_float_isinf(value) == (fc == kInfinite));
581cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    REPORTER_ASSERT(reporter, !!sk_float_isnan(value) == (fc == kNaN));
591cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
601cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
611cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic void test_isfinite(skiatest::Reporter* reporter) {
621cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#ifdef SK_CAN_USE_FLOAT
631cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    struct Rec {
641cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        float   fValue;
651cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        bool    fIsFinite;
661cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    };
671cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
681cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    float max = 3.402823466e+38f;
691cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    float inf = max * max;
701cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    float nan = inf * 0;
711cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
721cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    test_floatclass(reporter,    0, kFinite);
731cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    test_floatclass(reporter,  max, kFinite);
741cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    test_floatclass(reporter, -max, kFinite);
751cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    test_floatclass(reporter,  inf, kInfinite);
761cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    test_floatclass(reporter, -inf, kInfinite);
771cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    test_floatclass(reporter,  nan, kNaN);
781cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    test_floatclass(reporter, -nan, kNaN);
791cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
801cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    const Rec data[] = {
811cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        {   0,          true    },
821cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        {   1,          true    },
831cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        {  -1,          true    },
841cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        {  max * 0.75,  true    },
851cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        {  max,         true    },
861cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        {  -max * 0.75, true    },
871cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        {  -max,        true    },
881cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        {  inf,         false   },
891cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        { -inf,         false   },
901cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        {  nan,         false   },
911cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    };
921cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
931cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    const IsFiniteProc1 gProc1[] = {
941cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        isFinite_int,
951cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        isFinite_float,
961cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        isFinite_mulzero
971cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    };
981cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    const IsFiniteProc2 gProc2[] = {
991cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        isFinite2_and,
1001cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        isFinite2_mulzeroadd
1011cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    };
1021cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1031cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    size_t i, n = SK_ARRAY_COUNT(data);
1041cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1051cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    for (i = 0; i < n; ++i) {
1061cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        for (size_t k = 0; k < SK_ARRAY_COUNT(gProc1); ++k) {
1071cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            const Rec& rec = data[i];
1081cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            bool finite = gProc1[k](rec.fValue);
1091cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            REPORTER_ASSERT(reporter, rec.fIsFinite == finite);
1101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        }
1111cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
1121cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1131cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    for (i = 0; i < n; ++i) {
1141cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        const Rec& rec0 = data[i];
1151cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        for (size_t j = 0; j < n; ++j) {
1161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            const Rec& rec1 = data[j];
1171cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            for (size_t k = 0; k < SK_ARRAY_COUNT(gProc1); ++k) {
1181cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                IsFiniteProc1 proc1 = gProc1[k];
1191cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1201cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                for (size_t m = 0; m < SK_ARRAY_COUNT(gProc2); ++m) {
1211cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                    bool finite = gProc2[m](rec0.fValue, rec1.fValue, proc1);
1221cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                    bool finite2 = rec0.fIsFinite && rec1.fIsFinite;
1231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                    REPORTER_ASSERT(reporter, finite2 == finite);
1241cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                }
1251cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            }
1261cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        }
1271cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
1281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#endif
1291cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
1301cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1311cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic void TestScalar(skiatest::Reporter* reporter) {
1321cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    test_isfinite(reporter);
1331cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
1341cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1351cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#include "TestClassDef.h"
1361cab2921ab279367f8206cdadc9259d12e603548Derek SollenbergerDEFINE_TESTCLASS("Scalar", TestScalarClass, TestScalar)
1371cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
138