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