180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/*
380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright 2008 The Android Open Source Project
480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *
580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Use of this source code is governed by a BSD-style license that can be
680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * found in the LICENSE file.
780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */
880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkFloat.h"
1180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkMathPriv.h"
1280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define EXP_BIAS    (127+23)
1480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic int get_unsigned_exp(uint32_t packed)
1680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
1780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return (packed << 1 >> 24);
1880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
1980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
2080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic unsigned get_unsigned_value(uint32_t packed)
2180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
2280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return (packed << 9 >> 9) | (1 << 23);
2380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
2480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
2580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic int get_signed_value(int32_t packed)
2680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
2780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return SkApplySign(get_unsigned_value(packed), SkExtractSign(packed));
2880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
2980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/////////////////////////////////////////////////////////////////////////
3180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruint SkFloat::GetShift(int32_t packed, int shift)
3380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
3480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (packed == 0)
3580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return 0;
3680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int exp = get_unsigned_exp(packed) - EXP_BIAS - shift;
3880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int value = get_unsigned_value(packed);
3980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
4080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (exp >= 0)
4180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {
4280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (exp > 8)    // overflow
4380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            value = SK_MaxS32;
4480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        else
4580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            value <<= exp;
4680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
4780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    else
4880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {
4980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        exp = -exp;
5080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (exp > 23)   // underflow
5180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            value = 0;
5280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        else
5380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            value >>= exp;
5480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
5580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return SkApplySign(value, SkExtractSign(packed));
5680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
5780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
5880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/////////////////////////////////////////////////////////////////////////////////////
5980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
6080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruint32_t SkFloat::SetShift(int value, int shift)
6180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
6280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (value == 0)
6380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return 0;
6480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
6580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // record the sign and make value positive
6680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int sign = SkExtractSign(value);
6780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    value = SkApplySign(value, sign);
6880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
6980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (value >> 24)    // value is too big (has more than 24 bits set)
7080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {
7180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int bias = 8 - SkCLZ(value);
7280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(bias > 0 && bias < 8);
7380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        value >>= bias;
7480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        shift += bias;
7580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
7680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    else
7780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {
7880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int zeros = SkCLZ(value << 8);
7980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(zeros >= 0 && zeros <= 23);
8080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        value <<= zeros;
8180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        shift -= zeros;
8280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
8380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // now value is left-aligned to 24 bits
8480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT((value >> 23) == 1);
8580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
8680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    shift += EXP_BIAS;
8780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (shift < 0)  // underflow
8880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return 0;
8980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    else
9080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {
9180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (shift > 255)    // overflow
9280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        {
9380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            shift = 255;
9480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            value = 0x00FFFFFF;
9580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
9680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int32_t packed = sign << 31;        // set the sign-bit
9780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        packed |= shift << 23;          // store the packed exponent
9880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        packed |= ((unsigned)(value << 9) >> 9);    // clear 24th bit of value (its implied)
9980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
10080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_DEBUG
10180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        {
10280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            int n;
10380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
10480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            n = SkExtractSign(packed);
10580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkASSERT(n == sign);
10680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            n = get_unsigned_exp(packed);
10780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkASSERT(n == shift);
10880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            n = get_unsigned_value(packed);
10980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkASSERT(n == value);
11080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
11180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
11280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return packed;
11380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
11480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
11580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
11680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruint32_t SkFloat::Neg(int32_t packed)
11780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
11880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (packed)
11980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        packed = packed ^ (1 << 31);
12080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return packed;
12180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
12280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
12380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruint32_t SkFloat::Add(int32_t packed_a, int32_t packed_b)
12480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
12580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (packed_a == 0)
12680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return packed_b;
12780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (packed_b == 0)
12880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return packed_a;
12980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
13080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int exp_a = get_unsigned_exp(packed_a);
13180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int exp_b = get_unsigned_exp(packed_b);
13280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int exp_diff = exp_a - exp_b;
13380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
13480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int shift_a = 0, shift_b = 0;
13580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int exp;
13680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
13780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (exp_diff >= 0)
13880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {
13980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (exp_diff > 24)  // B is too small to contribute
14080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return packed_a;
14180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        shift_b = exp_diff;
14280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        exp = exp_a;
14380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
14480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    else
14580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {
14680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        exp_diff = -exp_diff;
14780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (exp_diff > 24)  // A is too small to contribute
14880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return packed_b;
14980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        shift_a = exp_diff;
15080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        exp = exp_b;
15180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
15280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
15380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int value_a = get_signed_value(packed_a) >> shift_a;
15480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int value_b = get_signed_value(packed_b) >> shift_b;
15580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
15680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return SkFloat::SetShift(value_a + value_b, exp - EXP_BIAS);
15780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
15880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
15980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "Sk64.h"
16080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
16180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline int32_t mul24(int32_t a, int32_t b)
16280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
16380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    Sk64 tmp;
16480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
16580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    tmp.setMul(a, b);
16680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    tmp.roundRight(24);
16780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return tmp.get32();
16880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
16980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
17080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruint32_t SkFloat::Mul(int32_t packed_a, int32_t packed_b)
17180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
17280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (packed_a == 0 || packed_b == 0)
17380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return 0;
17480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
17580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int exp_a = get_unsigned_exp(packed_a);
17680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int exp_b = get_unsigned_exp(packed_b);
17780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
17880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int value_a = get_signed_value(packed_a);
17980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int value_b = get_signed_value(packed_b);
18080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
18180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return SkFloat::SetShift(mul24(value_a, value_b), exp_a + exp_b - 2*EXP_BIAS + 24);
18280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
18380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
18480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruint32_t SkFloat::MulInt(int32_t packed, int n)
18580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
18680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return Mul(packed, SetShift(n, 0));
18780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
18880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
18980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruint32_t SkFloat::Div(int32_t packed_n, int32_t packed_d)
19080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
19180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(packed_d != 0);
19280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
19380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (packed_n == 0)
19480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return 0;
19580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
19680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int exp_n = get_unsigned_exp(packed_n);
19780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int exp_d = get_unsigned_exp(packed_d);
19880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
19980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int value_n = get_signed_value(packed_n);
20080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int value_d = get_signed_value(packed_d);
20180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
20280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return SkFloat::SetShift(SkDivBits(value_n, value_d, 24), exp_n - exp_d - 24);
20380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
20480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
20580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruint32_t SkFloat::DivInt(int32_t packed, int n)
20680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
20780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return Div(packed, SetShift(n, 0));
20880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
20980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
21080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruint32_t SkFloat::Invert(int32_t packed)
21180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
21280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return Div(packed, SetShift(1, 0));
21380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
21480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
21580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruint32_t SkFloat::Sqrt(int32_t packed)
21680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
21780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (packed < 0)
21880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {
21980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkDEBUGFAIL("can't sqrt a negative number");
22080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return 0;
22180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
22280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
22380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int exp = get_unsigned_exp(packed);
22480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int value = get_unsigned_value(packed);
22580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
22680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int nexp = exp - EXP_BIAS;
22780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int root = SkSqrtBits(value << (nexp & 1), 26);
22880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    nexp >>= 1;
22980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return SkFloat::SetShift(root, nexp - 11);
23080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
23180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
23280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if defined _WIN32 && _MSC_VER >= 1300  // disable warning : unreachable code
23380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#pragma warning ( push )
23480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#pragma warning ( disable : 4702 )
23580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
23680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
23780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruint32_t SkFloat::CubeRoot(int32_t packed)
23880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
23980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    sk_throw();
24080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return 0;
24180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
24280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
24380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if defined _WIN32 && _MSC_VER >= 1300
24480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#pragma warning ( pop )
24580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
24680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
24780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline int32_t clear_high_bit(int32_t n)
24880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
24980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return ((uint32_t)(n << 1)) >> 1;
25080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
25180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
25280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline int int_sign(int32_t a, int32_t b)
25380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
25480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return a > b ? 1 : (a < b ? -1 : 0);
25580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
25680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
25780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruint SkFloat::Cmp(int32_t packed_a, int32_t packed_b)
25880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
25980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    packed_a = SkApplySign(clear_high_bit(packed_a), SkExtractSign(packed_a));
26080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    packed_b = SkApplySign(clear_high_bit(packed_b), SkExtractSign(packed_b));
26180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
26280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return int_sign(packed_a, packed_b);
26380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
26480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
26580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/////////////////////////////////////////////////////////////////////////////////////
26680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/////////////////////////////////////////////////////////////////////////////////////
26780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
26880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_DEBUG
26980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
27080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkRandom.h"
27180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkFloatingPoint.h"
27280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
27380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkFloat::UnitTest()
27480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
27580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_SUPPORT_UNITTEST
27680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkFloat a, b, c, d;
27780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int     n;
27880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
27980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    a.setZero();
28080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    n = a.getInt();
28180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(n == 0);
28280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
28380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    b.setInt(5);
28480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    n = b.getInt();
28580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(n == 5);
28680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
28780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    c.setInt(-3);
28880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    n = c.getInt();
28980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(n == -3);
29080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
29180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    d.setAdd(c, b);
29280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkDebugf("SkFloat: %d + %d = %d\n", c.getInt(), b.getInt(), d.getInt());
29380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
294096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    SkMWCRandom    rand;
29580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
29680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int i;
29780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (i = 0; i < 1000; i++)
29880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {
29980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        float fa, fb;
30080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int aa = rand.nextS() >> 14;
30180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int bb = rand.nextS() >> 14;
30280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        a.setInt(aa);
30380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        b.setInt(bb);
30480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(a.getInt() == aa);
30580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(b.getInt() == bb);
30680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
30780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        c.setAdd(a, b);
30880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int cc = c.getInt();
30980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(cc == aa + bb);
31080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
31180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        c.setSub(a, b);
31280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        cc = c.getInt();
31380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(cc == aa - bb);
31480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
31580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        aa >>= 5;
31680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        bb >>= 5;
31780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        a.setInt(aa);
31880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        b.setInt(bb);
31980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        c.setMul(a, b);
32080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        cc = c.getInt();
32180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(cc == aa * bb);
32280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        /////////////////////////////////////
32380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
32480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        aa = rand.nextS() >> 11;
32580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        a.setFixed(aa);
32680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        cc = a.getFixed();
32780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(aa == cc);
32880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
32980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        bb = rand.nextS() >> 11;
33080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        b.setFixed(bb);
33180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        cc = b.getFixed();
33280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(bb == cc);
33380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
33480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        cc = SkFixedMul(aa, bb);
33580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        c.setMul(a, b);
33680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkFixed dd = c.getFixed();
33780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int diff = cc - dd;
33880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(SkAbs32(diff) <= 1);
33980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
34080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fa = (float)aa / 65536.0f;
34180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fb = (float)bb / 65536.0f;
34280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        a.assertEquals(fa);
34380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        b.assertEquals(fb);
34480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fa = a.getFloat();
34580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fb = b.getFloat();
34680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
34780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        c.assertEquals(fa * fb, 1);
34880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
34980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        c.setDiv(a, b);
35080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        cc = SkFixedDiv(aa, bb);
35180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        dd = c.getFixed();
35280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        diff = cc - dd;
35380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(SkAbs32(diff) <= 3);
35480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
35580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        c.assertEquals(fa / fb, 1);
35680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
35780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT((aa == bb) == (a == b));
35880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT((aa != bb) == (a != b));
35980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT((aa < bb) == (a < b));
36080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT((aa <= bb) == (a <= b));
36180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT((aa > bb) == (a > b));
36280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT((aa >= bb) == (a >= b));
36380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
36480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (aa < 0)
36580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        {
36680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            aa = -aa;
36780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fa = -fa;
36880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
36980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        a.setFixed(aa);
37080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        c.setSqrt(a);
37180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        cc = SkFixedSqrt(aa);
37280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        dd = c.getFixed();
37380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(dd == cc);
37480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
37580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        c.assertEquals(sk_float_sqrt(fa), 2);
37680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
37780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // cuberoot
37880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if 0
37980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        a.setInt(1);
38080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        a.cubeRoot();
38180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        a.assertEquals(1.0f, 0);
38280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        a.setInt(8);
38380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        a.cubeRoot();
38480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        a.assertEquals(2.0f, 0);
38580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        a.setInt(27);
38680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        a.cubeRoot();
38780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        a.assertEquals(3.0f, 0);
38880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
38980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
39080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
39180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
39280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
39380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
394