1685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com
2bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com/*
3685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * Copyright 2008 The Android Open Source Project
4bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com *
5685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * Use of this source code is governed by a BSD-style license that can be
6685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * found in the LICENSE file.
7bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com */
8bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
9685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com
10bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkFloat.h"
111b03b2b8c46cc230a5f78a5617526d35da9fb29ereed@google.com#include "SkMathPriv.h"
12bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
13bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#define EXP_BIAS    (127+23)
14bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
15bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comstatic int get_unsigned_exp(uint32_t packed)
16bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{
17bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    return (packed << 1 >> 24);
18bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
19bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
20bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comstatic unsigned get_unsigned_value(uint32_t packed)
21bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{
22bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    return (packed << 9 >> 9) | (1 << 23);
23bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
24bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
25bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comstatic int get_signed_value(int32_t packed)
26bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{
27bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    return SkApplySign(get_unsigned_value(packed), SkExtractSign(packed));
28bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
29bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
30bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com/////////////////////////////////////////////////////////////////////////
31bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
32bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comint SkFloat::GetShift(int32_t packed, int shift)
33bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{
34bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    if (packed == 0)
35bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        return 0;
36bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
37bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    int exp = get_unsigned_exp(packed) - EXP_BIAS - shift;
38bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    int value = get_unsigned_value(packed);
39bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
40bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    if (exp >= 0)
41bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    {
42bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        if (exp > 8)    // overflow
43bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            value = SK_MaxS32;
44bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        else
45bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            value <<= exp;
46bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
47bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    else
48bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    {
49bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        exp = -exp;
50bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        if (exp > 23)   // underflow
51bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            value = 0;
52bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        else
53bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            value >>= exp;
54bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
55bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    return SkApplySign(value, SkExtractSign(packed));
56bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
57bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
58bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com/////////////////////////////////////////////////////////////////////////////////////
59bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
60bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comint32_t SkFloat::SetShift(int value, int shift)
61bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{
62bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    if (value == 0)
63bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        return 0;
64bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
65bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    // record the sign and make value positive
66bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    int sign = SkExtractSign(value);
67bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    value = SkApplySign(value, sign);
68bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
69bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    if (value >> 24)    // value is too big (has more than 24 bits set)
70bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    {
71bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        int bias = 8 - SkCLZ(value);
72bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkASSERT(bias > 0 && bias < 8);
73bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        value >>= bias;
74bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        shift += bias;
75bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
76bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    else
77bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    {
78bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        int zeros = SkCLZ(value << 8);
79bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkASSERT(zeros >= 0 && zeros <= 23);
80bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        value <<= zeros;
81bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        shift -= zeros;
82bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
83bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    // now value is left-aligned to 24 bits
84bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkASSERT((value >> 23) == 1);
85bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
86bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    shift += EXP_BIAS;
87bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    if (shift < 0)  // underflow
88bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        return 0;
89bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    else
90bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    {
91bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        if (shift > 255)    // overflow
92bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        {
93bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            shift = 255;
94bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            value = 0x00FFFFFF;
95bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        }
96bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        int32_t packed = sign << 31;        // set the sign-bit
97bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        packed |= shift << 23;          // store the packed exponent
98bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        packed |= ((unsigned)(value << 9) >> 9);    // clear 24th bit of value (its implied)
99bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
100bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#ifdef SK_DEBUG
101bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        {
102bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            int n;
103bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
104bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            n = SkExtractSign(packed);
105bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            SkASSERT(n == sign);
106bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            n = get_unsigned_exp(packed);
107bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            SkASSERT(n == shift);
108bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            n = get_unsigned_value(packed);
109bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            SkASSERT(n == value);
110bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        }
111bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif
112bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        return packed;
113bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
114bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
115bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
116bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comint32_t SkFloat::Neg(int32_t packed)
117bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{
118bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    if (packed)
119bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        packed = packed ^ (1 << 31);
120bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    return packed;
121bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
122bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
123bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comint32_t SkFloat::Add(int32_t packed_a, int32_t packed_b)
124bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{
125bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    if (packed_a == 0)
126bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        return packed_b;
127bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    if (packed_b == 0)
128bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        return packed_a;
129bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
130bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    int exp_a = get_unsigned_exp(packed_a);
131bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    int exp_b = get_unsigned_exp(packed_b);
132bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    int exp_diff = exp_a - exp_b;
133bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
134bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    int shift_a = 0, shift_b = 0;
135bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    int exp;
136bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
137bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    if (exp_diff >= 0)
138bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    {
139bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        if (exp_diff > 24)  // B is too small to contribute
140bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            return packed_a;
141bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        shift_b = exp_diff;
142bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        exp = exp_a;
143bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
144bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    else
145bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    {
146bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        exp_diff = -exp_diff;
147bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        if (exp_diff > 24)  // A is too small to contribute
148bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            return packed_b;
149bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        shift_a = exp_diff;
150bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        exp = exp_b;
151bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
152bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
153bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    int value_a = get_signed_value(packed_a) >> shift_a;
154bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    int value_b = get_signed_value(packed_b) >> shift_b;
155bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
156bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    return SkFloat::SetShift(value_a + value_b, exp - EXP_BIAS);
157bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
158bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
159bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "Sk64.h"
160bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
161bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comstatic inline int32_t mul24(int32_t a, int32_t b)
162bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{
163bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    Sk64 tmp;
164bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
165bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    tmp.setMul(a, b);
166bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    tmp.roundRight(24);
167bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    return tmp.get32();
168bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
169bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
170bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comint32_t SkFloat::Mul(int32_t packed_a, int32_t packed_b)
171bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{
172bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    if (packed_a == 0 || packed_b == 0)
173bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        return 0;
174bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
175bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    int exp_a = get_unsigned_exp(packed_a);
176bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    int exp_b = get_unsigned_exp(packed_b);
177bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
178bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    int value_a = get_signed_value(packed_a);
179bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    int value_b = get_signed_value(packed_b);
180bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
181bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    return SkFloat::SetShift(mul24(value_a, value_b), exp_a + exp_b - 2*EXP_BIAS + 24);
182bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
183bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
184bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comint32_t SkFloat::MulInt(int32_t packed, int n)
185bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{
186bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    return Mul(packed, SetShift(n, 0));
187bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
188bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
189bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comint32_t SkFloat::Div(int32_t packed_n, int32_t packed_d)
190bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{
191bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkASSERT(packed_d != 0);
192bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
193bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    if (packed_n == 0)
194bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        return 0;
195bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
196bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    int exp_n = get_unsigned_exp(packed_n);
197bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    int exp_d = get_unsigned_exp(packed_d);
198bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
199bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    int value_n = get_signed_value(packed_n);
200bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    int value_d = get_signed_value(packed_d);
201bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
202bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    return SkFloat::SetShift(SkDivBits(value_n, value_d, 24), exp_n - exp_d - 24);
203bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
204bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
205bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comint32_t SkFloat::DivInt(int32_t packed, int n)
206bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{
207bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    return Div(packed, SetShift(n, 0));
208bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
209bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
210bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comint32_t SkFloat::Invert(int32_t packed)
211bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{
212bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    return Div(packed, SetShift(1, 0));
213bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
214bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
215bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comint32_t SkFloat::Sqrt(int32_t packed)
216bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{
217bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    if (packed < 0)
218bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    {
2192d7de2d243beab591671dfaf535a637b5d305735tomhudson@google.com        SkDEBUGFAIL("can't sqrt a negative number");
220bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        return 0;
221bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
222bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
223bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    int exp = get_unsigned_exp(packed);
224bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    int value = get_unsigned_value(packed);
225bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
226bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    int nexp = exp - EXP_BIAS;
227bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    int root = SkSqrtBits(value << (nexp & 1), 26);
228bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    nexp >>= 1;
229bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    return SkFloat::SetShift(root, nexp - 11);
230bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
231bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
232bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#if defined _WIN32 && _MSC_VER >= 1300  // disable warning : unreachable code
233bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#pragma warning ( push )
234bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#pragma warning ( disable : 4702 )
235bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif
236bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
237bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comint32_t SkFloat::CubeRoot(int32_t packed)
238bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{
239bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    sk_throw();
240bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    return 0;
241bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
242bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
243bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#if defined _WIN32 && _MSC_VER >= 1300
244bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#pragma warning ( pop )
245bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif
246bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
247bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comstatic inline int32_t clear_high_bit(int32_t n)
248bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{
249bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    return ((uint32_t)(n << 1)) >> 1;
250bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
251bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
252bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comstatic inline int int_sign(int32_t a, int32_t b)
253bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{
254bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    return a > b ? 1 : (a < b ? -1 : 0);
255bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
256bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
257bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comint SkFloat::Cmp(int32_t packed_a, int32_t packed_b)
258bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{
259bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    packed_a = SkApplySign(clear_high_bit(packed_a), SkExtractSign(packed_a));
260bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    packed_b = SkApplySign(clear_high_bit(packed_b), SkExtractSign(packed_b));
261bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
262bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    return int_sign(packed_a, packed_b);
263bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
264bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
265bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com/////////////////////////////////////////////////////////////////////////////////////
266bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com/////////////////////////////////////////////////////////////////////////////////////
267bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
268bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#ifdef SK_DEBUG
269bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
270bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkRandom.h"
2713dceba326fadf107085ff7c10e5fd56ba1715c09reed@google.com#include "SkFloatingPoint.h"
272bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
273bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkFloat::UnitTest()
274bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{
275bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#ifdef SK_SUPPORT_UNITTEST
276bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkFloat a, b, c, d;
277bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    int     n;
278bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
279bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    a.setZero();
280bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    n = a.getInt();
281bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkASSERT(n == 0);
282bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
283bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    b.setInt(5);
284bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    n = b.getInt();
285bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkASSERT(n == 5);
286bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
287bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    c.setInt(-3);
288bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    n = c.getInt();
289bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkASSERT(n == -3);
290bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
291bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    d.setAdd(c, b);
292935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com    SkDebugf("SkFloat: %d + %d = %d\n", c.getInt(), b.getInt(), d.getInt());
293bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
2941f875ad11f8302b5c0b136d2bb795b2f4c0707b3jvanverth@google.com    SkMWCRandom    rand;
295bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
296bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    int i;
297bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    for (i = 0; i < 1000; i++)
298bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    {
299bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        float fa, fb;
300bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        int aa = rand.nextS() >> 14;
301bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        int bb = rand.nextS() >> 14;
302bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        a.setInt(aa);
303bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        b.setInt(bb);
304bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkASSERT(a.getInt() == aa);
305bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkASSERT(b.getInt() == bb);
306bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
307bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        c.setAdd(a, b);
308bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        int cc = c.getInt();
309bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkASSERT(cc == aa + bb);
310bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
311bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        c.setSub(a, b);
312bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        cc = c.getInt();
313bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkASSERT(cc == aa - bb);
314bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
315bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        aa >>= 5;
316bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        bb >>= 5;
317bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        a.setInt(aa);
318bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        b.setInt(bb);
319bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        c.setMul(a, b);
320bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        cc = c.getInt();
321bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkASSERT(cc == aa * bb);
322bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        /////////////////////////////////////
323bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
324bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        aa = rand.nextS() >> 11;
325bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        a.setFixed(aa);
326bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        cc = a.getFixed();
327bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkASSERT(aa == cc);
328bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
329bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        bb = rand.nextS() >> 11;
330bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        b.setFixed(bb);
331bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        cc = b.getFixed();
332bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkASSERT(bb == cc);
333bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
334bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        cc = SkFixedMul(aa, bb);
335bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        c.setMul(a, b);
336bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkFixed dd = c.getFixed();
337bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        int diff = cc - dd;
338bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkASSERT(SkAbs32(diff) <= 1);
339bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
340bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fa = (float)aa / 65536.0f;
341bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fb = (float)bb / 65536.0f;
342bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        a.assertEquals(fa);
343bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        b.assertEquals(fb);
344bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fa = a.getFloat();
345bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fb = b.getFloat();
346bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
347bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        c.assertEquals(fa * fb, 1);
348bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
349bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        c.setDiv(a, b);
350bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        cc = SkFixedDiv(aa, bb);
351bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        dd = c.getFixed();
352bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        diff = cc - dd;
353bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkASSERT(SkAbs32(diff) <= 3);
354bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
355bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        c.assertEquals(fa / fb, 1);
356bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
357bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkASSERT((aa == bb) == (a == b));
358bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkASSERT((aa != bb) == (a != b));
359bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkASSERT((aa < bb) == (a < b));
360bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkASSERT((aa <= bb) == (a <= b));
361bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkASSERT((aa > bb) == (a > b));
362bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkASSERT((aa >= bb) == (a >= b));
363bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
364bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        if (aa < 0)
365bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        {
366bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            aa = -aa;
367bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            fa = -fa;
368bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        }
369bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        a.setFixed(aa);
370bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        c.setSqrt(a);
371bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        cc = SkFixedSqrt(aa);
372bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        dd = c.getFixed();
373bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkASSERT(dd == cc);
374bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
375bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        c.assertEquals(sk_float_sqrt(fa), 2);
376bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
377bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        // cuberoot
378bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#if 0
379bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        a.setInt(1);
380bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        a.cubeRoot();
381bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        a.assertEquals(1.0f, 0);
382bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        a.setInt(8);
383bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        a.cubeRoot();
384bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        a.assertEquals(2.0f, 0);
385bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        a.setInt(27);
386bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        a.cubeRoot();
387bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        a.assertEquals(3.0f, 0);
388bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif
389bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
390bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif
391bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
392bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
393bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif
394