Home | History | Annotate | Download | only in tests
      1 
      2 /*
      3  * Copyright 2011 Google Inc.
      4  *
      5  * Use of this source code is governed by a BSD-style license that can be
      6  * found in the LICENSE file.
      7  */
      8 #include "Test.h"
      9 #include "SkRandom.h"
     10 #include <math.h>
     11 
     12 struct BoolTable {
     13     int8_t  zero, pos, neg, toBool, sign;
     14 };
     15 
     16 static void bool_table_test(skiatest::Reporter* reporter,
     17                             const Sk64& a, const BoolTable& table)
     18 {
     19     REPORTER_ASSERT(reporter, a.isZero() != a.nonZero());
     20 
     21     REPORTER_ASSERT(reporter, !a.isZero() == !table.zero);
     22     REPORTER_ASSERT(reporter, !a.isPos() == !table.pos);
     23     REPORTER_ASSERT(reporter, !a.isNeg() == !table.neg);
     24     REPORTER_ASSERT(reporter, a.getSign() == table.sign);
     25 }
     26 
     27 #ifdef SkLONGLONG
     28     static SkLONGLONG asLL(const Sk64& a)
     29     {
     30         return ((SkLONGLONG)a.fHi << 32) | a.fLo;
     31     }
     32 #endif
     33 
     34 static void TestSk64(skiatest::Reporter* reporter) {
     35     enum BoolTests {
     36         kZero_BoolTest,
     37         kPos_BoolTest,
     38         kNeg_BoolTest
     39     };
     40     static const BoolTable gBoolTable[] = {
     41         { 1, 0, 0, 0, 0 },
     42         { 0, 1, 0, 1, 1 },
     43         { 0, 0, 1, 1, -1 }
     44     };
     45 
     46     Sk64    a, b, c;
     47 
     48     a.fHi = a.fLo = 0;
     49     b.set(0);
     50     c.setZero();
     51     REPORTER_ASSERT(reporter, a == b);
     52     REPORTER_ASSERT(reporter, a == c);
     53     bool_table_test(reporter, a, gBoolTable[kZero_BoolTest]);
     54 
     55     a.fHi = 0;  a.fLo = 5;
     56     b.set(5);
     57     REPORTER_ASSERT(reporter, a == b);
     58     REPORTER_ASSERT(reporter, a.is32() && a.get32() == 5 && !a.is64());
     59     bool_table_test(reporter, a, gBoolTable[kPos_BoolTest]);
     60 
     61     a.fHi = -1; a.fLo = (uint32_t)-5;
     62     b.set(-5);
     63     REPORTER_ASSERT(reporter, a == b);
     64     REPORTER_ASSERT(reporter, a.is32() && a.get32() == -5 && !a.is64());
     65     bool_table_test(reporter, a, gBoolTable[kNeg_BoolTest]);
     66 
     67     a.setZero();
     68     b.set(6);
     69     c.set(-6);
     70     REPORTER_ASSERT(reporter, a != b && b != c && a != c);
     71     REPORTER_ASSERT(reporter, !(a == b) && !(a == b) && !(a == b));
     72     REPORTER_ASSERT(reporter, a < b && b > a && a <= b && b >= a);
     73     REPORTER_ASSERT(reporter, c < a && a > c && c <= a && a >= c);
     74     REPORTER_ASSERT(reporter, c < b && b > c && c <= b && b >= c);
     75 
     76     // Now test add/sub
     77 
     78     SkRandom    rand;
     79     int         i;
     80 
     81     for (i = 0; i < 1000; i++)
     82     {
     83         int aa = rand.nextS() >> 1;
     84         int bb = rand.nextS() >> 1;
     85         a.set(aa);
     86         b.set(bb);
     87         REPORTER_ASSERT(reporter, a.get32() == aa && b.get32() == bb);
     88         c = a; c.add(bb);
     89         REPORTER_ASSERT(reporter, c.get32() == aa + bb);
     90         c = a; c.add(-bb);
     91         REPORTER_ASSERT(reporter, c.get32() == aa - bb);
     92         c = a; c.add(b);
     93         REPORTER_ASSERT(reporter, c.get32() == aa + bb);
     94         c = a; c.sub(b);
     95         REPORTER_ASSERT(reporter, c.get32() == aa - bb);
     96     }
     97 
     98 #ifdef SkLONGLONG
     99     for (i = 0; i < 1000; i++)
    100     {
    101         rand.next64(&a); //a.fHi >>= 1; // avoid overflow
    102         rand.next64(&b); //b.fHi >>= 1; // avoid overflow
    103 
    104         if (!(i & 3))   // want to explicitly test these cases
    105         {
    106             a.fLo = 0;
    107             b.fLo = 0;
    108         }
    109         else if (!(i & 7))  // want to explicitly test these cases
    110         {
    111             a.fHi = 0;
    112             b.fHi = 0;
    113         }
    114 
    115         SkLONGLONG aa = asLL(a);
    116         SkLONGLONG bb = asLL(b);
    117 
    118         REPORTER_ASSERT(reporter, (a < b) == (aa < bb));
    119         REPORTER_ASSERT(reporter, (a <= b) == (aa <= bb));
    120         REPORTER_ASSERT(reporter, (a > b) == (aa > bb));
    121         REPORTER_ASSERT(reporter, (a >= b) == (aa >= bb));
    122         REPORTER_ASSERT(reporter, (a == b) == (aa == bb));
    123         REPORTER_ASSERT(reporter, (a != b) == (aa != bb));
    124 
    125         c = a; c.add(b);
    126         REPORTER_ASSERT(reporter, asLL(c) == aa + bb);
    127         c = a; c.sub(b);
    128         REPORTER_ASSERT(reporter, asLL(c) == aa - bb);
    129         c = a; c.rsub(b);
    130         REPORTER_ASSERT(reporter, asLL(c) == bb - aa);
    131         c = a; c.negate();
    132         REPORTER_ASSERT(reporter, asLL(c) == -aa);
    133 
    134         int bits = rand.nextU() & 63;
    135         c = a; c.shiftLeft(bits);
    136         REPORTER_ASSERT(reporter, asLL(c) == (aa << bits));
    137         c = a; c.shiftRight(bits);
    138         REPORTER_ASSERT(reporter, asLL(c) == (aa >> bits));
    139         c = a; c.roundRight(bits);
    140 
    141         SkLONGLONG tmp;
    142 
    143         tmp = aa;
    144         if (bits > 0)
    145             tmp += (SkLONGLONG)1 << (bits - 1);
    146         REPORTER_ASSERT(reporter, asLL(c) == (tmp >> bits));
    147 
    148         c.setMul(a.fHi, b.fHi);
    149         tmp = (SkLONGLONG)a.fHi * b.fHi;
    150         REPORTER_ASSERT(reporter, asLL(c) == tmp);
    151     }
    152 
    153 
    154     for (i = 0; i < 100000; i++)
    155     {
    156         Sk64    wide;
    157         int32_t denom = rand.nextS();
    158 
    159         while (denom == 0)
    160             denom = rand.nextS();
    161         wide.setMul(rand.nextS(), rand.nextS());
    162         SkLONGLONG check = wide.getLongLong();
    163 
    164         wide.div(denom, Sk64::kTrunc_DivOption);
    165         check /= denom;
    166         SkLONGLONG w = wide.getLongLong();
    167 
    168         REPORTER_ASSERT(reporter, check == w);
    169 
    170 #ifdef SK_CAN_USE_FLOAT
    171         wide.setMul(rand.nextS(), rand.nextS());
    172         wide.abs();
    173         denom = wide.getSqrt();
    174         int32_t ck = (int32_t)sqrt((double)wide.getLongLong());
    175         int diff = denom - ck;
    176         REPORTER_ASSERT(reporter, SkAbs32(diff) <= 1);
    177 
    178         wide.setMul(rand.nextS(), rand.nextS());
    179         Sk64    dwide;
    180         dwide.setMul(rand.nextS(), rand.nextS());
    181         SkFixed fixdiv = wide.getFixedDiv(dwide);
    182         double dnumer = (double)wide.getLongLong();
    183         double ddenom = (double)dwide.getLongLong();
    184         double ddiv = dnumer / ddenom;
    185         SkFixed dfixdiv;
    186         if (ddiv >= (double)SK_MaxS32 / (double)SK_Fixed1)
    187             dfixdiv = SK_MaxS32;
    188         else if (ddiv <= -(double)SK_MaxS32 / (double)SK_Fixed1)
    189             dfixdiv = SK_MinS32;
    190         else
    191             dfixdiv = SkFloatToFixed(dnumer / ddenom);
    192         diff = fixdiv - dfixdiv;
    193 
    194         if (SkAbs32(diff) > 1) {
    195             SkDebugf(" %d === numer %g denom %g div %g xdiv %x fxdiv %x\n",
    196                      i, dnumer, ddenom, ddiv, dfixdiv, fixdiv);
    197         }
    198         REPORTER_ASSERT(reporter, SkAbs32(diff) <= 1);
    199 #endif
    200     }
    201 #endif
    202 }
    203 
    204 #include "TestClassDef.h"
    205 DEFINE_TESTCLASS("Sk64", Sk64TestClass, TestSk64)
    206