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 "TestClassDef.h"
     10 #include "SkRandom.h"
     11 #include <math.h>
     12 
     13 struct BoolTable {
     14     int8_t  zero, pos, neg, toBool, sign;
     15 };
     16 
     17 static void bool_table_test(skiatest::Reporter* reporter,
     18                             const Sk64& a, const BoolTable& table)
     19 {
     20     REPORTER_ASSERT(reporter, a.isZero() != a.nonZero());
     21 
     22     REPORTER_ASSERT(reporter, !a.isZero() == !table.zero);
     23     REPORTER_ASSERT(reporter, !a.isPos() == !table.pos);
     24     REPORTER_ASSERT(reporter, !a.isNeg() == !table.neg);
     25     REPORTER_ASSERT(reporter, a.getSign() == table.sign);
     26 }
     27 
     28 #ifdef SkLONGLONG
     29     static SkLONGLONG asLL(const Sk64& a)
     30     {
     31         return ((SkLONGLONG)a.fHi << 32) | a.fLo;
     32     }
     33 #endif
     34 
     35 DEF_TEST(Sk64Test, reporter) {
     36     enum BoolTests {
     37         kZero_BoolTest,
     38         kPos_BoolTest,
     39         kNeg_BoolTest
     40     };
     41     static const BoolTable gBoolTable[] = {
     42         { 1, 0, 0, 0, 0 },
     43         { 0, 1, 0, 1, 1 },
     44         { 0, 0, 1, 1, -1 }
     45     };
     46 
     47     Sk64    a, b, c;
     48 
     49     a.fHi = a.fLo = 0;
     50     b.set(0);
     51     c.setZero();
     52     REPORTER_ASSERT(reporter, a == b);
     53     REPORTER_ASSERT(reporter, a == c);
     54     bool_table_test(reporter, a, gBoolTable[kZero_BoolTest]);
     55 
     56     a.fHi = 0;  a.fLo = 5;
     57     b.set(5);
     58     REPORTER_ASSERT(reporter, a == b);
     59     REPORTER_ASSERT(reporter, a.is32() && a.get32() == 5 && !a.is64());
     60     bool_table_test(reporter, a, gBoolTable[kPos_BoolTest]);
     61 
     62     a.fHi = -1; a.fLo = (uint32_t)-5;
     63     b.set(-5);
     64     REPORTER_ASSERT(reporter, a == b);
     65     REPORTER_ASSERT(reporter, a.is32() && a.get32() == -5 && !a.is64());
     66     bool_table_test(reporter, a, gBoolTable[kNeg_BoolTest]);
     67 
     68     a.setZero();
     69     b.set(6);
     70     c.set(-6);
     71     REPORTER_ASSERT(reporter, a != b && b != c && a != c);
     72     REPORTER_ASSERT(reporter, !(a == b) && !(a == b) && !(a == b));
     73     REPORTER_ASSERT(reporter, a < b && b > a && a <= b && b >= a);
     74     REPORTER_ASSERT(reporter, c < a && a > c && c <= a && a >= c);
     75     REPORTER_ASSERT(reporter, c < b && b > c && c <= b && b >= c);
     76 
     77     // Now test add/sub
     78 
     79     SkRandom    rand;
     80     int         i;
     81 
     82     for (i = 0; i < 1000; i++)
     83     {
     84         int aa = rand.nextS() >> 1;
     85         int bb = rand.nextS() >> 1;
     86         a.set(aa);
     87         b.set(bb);
     88         REPORTER_ASSERT(reporter, a.get32() == aa && b.get32() == bb);
     89         c = a; c.add(bb);
     90         REPORTER_ASSERT(reporter, c.get32() == aa + bb);
     91         c = a; c.add(-bb);
     92         REPORTER_ASSERT(reporter, c.get32() == aa - bb);
     93         c = a; c.add(b);
     94         REPORTER_ASSERT(reporter, c.get32() == aa + bb);
     95         c = a; c.sub(b);
     96         REPORTER_ASSERT(reporter, c.get32() == aa - bb);
     97     }
     98 
     99 #ifdef SkLONGLONG
    100     for (i = 0; i < 1000; i++)
    101     {
    102         rand.next64(&a); //a.fHi >>= 1; // avoid overflow
    103         rand.next64(&b); //b.fHi >>= 1; // avoid overflow
    104 
    105         if (!(i & 3))   // want to explicitly test these cases
    106         {
    107             a.fLo = 0;
    108             b.fLo = 0;
    109         }
    110         else if (!(i & 7))  // want to explicitly test these cases
    111         {
    112             a.fHi = 0;
    113             b.fHi = 0;
    114         }
    115 
    116         SkLONGLONG aa = asLL(a);
    117         SkLONGLONG bb = asLL(b);
    118 
    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         REPORTER_ASSERT(reporter, (a != b) == (aa != bb));
    125 
    126         c = a; c.add(b);
    127         REPORTER_ASSERT(reporter, asLL(c) == aa + bb);
    128         c = a; c.sub(b);
    129         REPORTER_ASSERT(reporter, asLL(c) == aa - bb);
    130         c = a; c.rsub(b);
    131         REPORTER_ASSERT(reporter, asLL(c) == bb - aa);
    132         c = a; c.negate();
    133         REPORTER_ASSERT(reporter, asLL(c) == -aa);
    134 
    135         int bits = rand.nextU() & 63;
    136         c = a; c.shiftLeft(bits);
    137         REPORTER_ASSERT(reporter, asLL(c) == (aa << bits));
    138         c = a; c.shiftRight(bits);
    139         REPORTER_ASSERT(reporter, asLL(c) == (aa >> bits));
    140         c = a; c.roundRight(bits);
    141 
    142         SkLONGLONG tmp;
    143 
    144         tmp = aa;
    145         if (bits > 0)
    146             tmp += (SkLONGLONG)1 << (bits - 1);
    147         REPORTER_ASSERT(reporter, asLL(c) == (tmp >> bits));
    148 
    149         c.setMul(a.fHi, b.fHi);
    150         tmp = (SkLONGLONG)a.fHi * b.fHi;
    151         REPORTER_ASSERT(reporter, asLL(c) == tmp);
    152     }
    153 
    154 
    155     for (i = 0; i < 100000; i++)
    156     {
    157         Sk64    wide;
    158         int32_t denom = rand.nextS();
    159 
    160         while (denom == 0)
    161             denom = rand.nextS();
    162         wide.setMul(rand.nextS(), rand.nextS());
    163         SkLONGLONG check = wide.getLongLong();
    164 
    165         wide.div(denom, Sk64::kTrunc_DivOption);
    166         check /= denom;
    167         SkLONGLONG w = wide.getLongLong();
    168 
    169         REPORTER_ASSERT(reporter, check == w);
    170 
    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     }
    200 #endif
    201 }
    202