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