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