1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
28a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2008 The Android Open Source Project
48a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
78a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */
88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkFloat.h"
114b163ed2c22facbe8891616874ae07ba7827d9c9reed@google.com#include "SkMathPriv.h"
128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define EXP_BIAS    (127+23)
148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic int get_unsigned_exp(uint32_t packed)
168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (packed << 1 >> 24);
188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic unsigned get_unsigned_value(uint32_t packed)
218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (packed << 9 >> 9) | (1 << 23);
238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic int get_signed_value(int32_t packed)
268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkApplySign(get_unsigned_value(packed), SkExtractSign(packed));
288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////
318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkFloat::GetShift(int32_t packed, int shift)
338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (packed == 0)
358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return 0;
368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int exp = get_unsigned_exp(packed) - EXP_BIAS - shift;
388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int value = get_unsigned_value(packed);
398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (exp >= 0)
418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    {
428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (exp > 8)    // overflow
438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            value = SK_MaxS32;
448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        else
458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            value <<= exp;
468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    else
488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    {
498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        exp = -exp;
508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (exp > 23)   // underflow
518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            value = 0;
528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        else
538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            value >>= exp;
548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkApplySign(value, SkExtractSign(packed));
568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////////////
598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint32_t SkFloat::SetShift(int value, int shift)
618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (value == 0)
638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return 0;
648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // record the sign and make value positive
668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int sign = SkExtractSign(value);
678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    value = SkApplySign(value, sign);
688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (value >> 24)    // value is too big (has more than 24 bits set)
708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    {
718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int bias = 8 - SkCLZ(value);
728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(bias > 0 && bias < 8);
738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        value >>= bias;
748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        shift += bias;
758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    else
778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    {
788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int zeros = SkCLZ(value << 8);
798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(zeros >= 0 && zeros <= 23);
808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        value <<= zeros;
818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        shift -= zeros;
828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // now value is left-aligned to 24 bits
848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT((value >> 23) == 1);
858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    shift += EXP_BIAS;
878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (shift < 0)  // underflow
888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return 0;
898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    else
908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    {
918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (shift > 255)    // overflow
928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        {
938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            shift = 255;
948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            value = 0x00FFFFFF;
958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int32_t packed = sign << 31;        // set the sign-bit
978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        packed |= shift << 23;          // store the packed exponent
988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        packed |= ((unsigned)(value << 9) >> 9);    // clear 24th bit of value (its implied)
998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG
1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        {
1028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            int n;
1038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            n = SkExtractSign(packed);
1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkASSERT(n == sign);
1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            n = get_unsigned_exp(packed);
1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkASSERT(n == shift);
1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            n = get_unsigned_value(packed);
1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkASSERT(n == value);
1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return packed;
1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint32_t SkFloat::Neg(int32_t packed)
1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (packed)
1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        packed = packed ^ (1 << 31);
1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return packed;
1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint32_t SkFloat::Add(int32_t packed_a, int32_t packed_b)
1248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (packed_a == 0)
1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return packed_b;
1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (packed_b == 0)
1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return packed_a;
1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int exp_a = get_unsigned_exp(packed_a);
1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int exp_b = get_unsigned_exp(packed_b);
1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int exp_diff = exp_a - exp_b;
1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int shift_a = 0, shift_b = 0;
1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int exp;
1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (exp_diff >= 0)
1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    {
1398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (exp_diff > 24)  // B is too small to contribute
1408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return packed_a;
1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        shift_b = exp_diff;
1428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        exp = exp_a;
1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    else
1458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    {
1468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        exp_diff = -exp_diff;
1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (exp_diff > 24)  // A is too small to contribute
1488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return packed_b;
1498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        shift_a = exp_diff;
1508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        exp = exp_b;
1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int value_a = get_signed_value(packed_a) >> shift_a;
1548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int value_b = get_signed_value(packed_b) >> shift_b;
1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkFloat::SetShift(value_a + value_b, exp - EXP_BIAS);
1578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
159bf0001d0472d727266762c5967ec0d919a6df083reed@google.comstatic inline int32_t mul24(int32_t a, int32_t b) {
160bf0001d0472d727266762c5967ec0d919a6df083reed@google.com    int64_t tmp = (sk_64_mul(a, b) + (1 << 23)) >> 24;
161bf0001d0472d727266762c5967ec0d919a6df083reed@google.com    return sk_64_asS32(tmp);
1628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint32_t SkFloat::Mul(int32_t packed_a, int32_t packed_b)
1658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
1668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (packed_a == 0 || packed_b == 0)
1678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return 0;
1688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int exp_a = get_unsigned_exp(packed_a);
1708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int exp_b = get_unsigned_exp(packed_b);
1718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int value_a = get_signed_value(packed_a);
1738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int value_b = get_signed_value(packed_b);
1748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkFloat::SetShift(mul24(value_a, value_b), exp_a + exp_b - 2*EXP_BIAS + 24);
1768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint32_t SkFloat::MulInt(int32_t packed, int n)
1798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
1808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return Mul(packed, SetShift(n, 0));
1818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint32_t SkFloat::Div(int32_t packed_n, int32_t packed_d)
1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
1858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(packed_d != 0);
1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (packed_n == 0)
1888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return 0;
1898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int exp_n = get_unsigned_exp(packed_n);
1918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int exp_d = get_unsigned_exp(packed_d);
1928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int value_n = get_signed_value(packed_n);
1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int value_d = get_signed_value(packed_d);
1958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkFloat::SetShift(SkDivBits(value_n, value_d, 24), exp_n - exp_d - 24);
1978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint32_t SkFloat::DivInt(int32_t packed, int n)
2008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
2018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return Div(packed, SetShift(n, 0));
2028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint32_t SkFloat::Invert(int32_t packed)
2058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
2068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return Div(packed, SetShift(1, 0));
2078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint32_t SkFloat::Sqrt(int32_t packed)
2108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
2118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (packed < 0)
2128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    {
2130c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com        SkDEBUGFAIL("can't sqrt a negative number");
2148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return 0;
2158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int exp = get_unsigned_exp(packed);
2188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int value = get_unsigned_value(packed);
2198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int nexp = exp - EXP_BIAS;
2218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int root = SkSqrtBits(value << (nexp & 1), 26);
2228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    nexp >>= 1;
2238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkFloat::SetShift(root, nexp - 11);
2248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#if defined _WIN32 && _MSC_VER >= 1300  // disable warning : unreachable code
2278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#pragma warning ( push )
2288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#pragma warning ( disable : 4702 )
2298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
2308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint32_t SkFloat::CubeRoot(int32_t packed)
2328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
2338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    sk_throw();
2348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return 0;
2358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#if defined _WIN32 && _MSC_VER >= 1300
2388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#pragma warning ( pop )
2398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
2408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline int32_t clear_high_bit(int32_t n)
2428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
2438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return ((uint32_t)(n << 1)) >> 1;
2448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline int int_sign(int32_t a, int32_t b)
2478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
2488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return a > b ? 1 : (a < b ? -1 : 0);
2498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkFloat::Cmp(int32_t packed_a, int32_t packed_b)
2528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
2538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    packed_a = SkApplySign(clear_high_bit(packed_a), SkExtractSign(packed_a));
2548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    packed_b = SkApplySign(clear_high_bit(packed_b), SkExtractSign(packed_b));
2558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return int_sign(packed_a, packed_b);
2578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////////////
2608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////////////
2618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG
2638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkRandom.h"
2657886ad3de1aa523d5c71f1fa9f355dfcb2412d1dreed@google.com#include "SkFloatingPoint.h"
2668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkFloat::UnitTest()
2688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
269385afd8b7127b5578d6f272e6b9e7080c2afd229robertphillips@google.com#if 0 // def SK_SUPPORT_UNITTEST
2708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkFloat a, b, c, d;
2718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int     n;
2728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    a.setZero();
2748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    n = a.getInt();
2758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(n == 0);
2768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    b.setInt(5);
2788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    n = b.getInt();
2798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(n == 5);
2808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    c.setInt(-3);
2828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    n = c.getInt();
2838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(n == -3);
2848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    d.setAdd(c, b);
286fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    SkDebugf("SkFloat: %d + %d = %d\n", c.getInt(), b.getInt(), d.getInt());
2878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
288e0e7cfe44bb9d66d76120a79e5275c294bacaa22commit-bot@chromium.org    SkRandom    rand;
2898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int i;
2918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for (i = 0; i < 1000; i++)
2928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    {
2938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        float fa, fb;
2948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int aa = rand.nextS() >> 14;
2958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int bb = rand.nextS() >> 14;
2968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        a.setInt(aa);
2978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        b.setInt(bb);
2988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(a.getInt() == aa);
2998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(b.getInt() == bb);
3008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        c.setAdd(a, b);
3028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int cc = c.getInt();
3038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(cc == aa + bb);
3048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        c.setSub(a, b);
3068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        cc = c.getInt();
3078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(cc == aa - bb);
3088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        aa >>= 5;
3108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        bb >>= 5;
3118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        a.setInt(aa);
3128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        b.setInt(bb);
3138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        c.setMul(a, b);
3148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        cc = c.getInt();
3158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(cc == aa * bb);
3168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        /////////////////////////////////////
3178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        aa = rand.nextS() >> 11;
3198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        a.setFixed(aa);
3208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        cc = a.getFixed();
3218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(aa == cc);
3228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        bb = rand.nextS() >> 11;
3248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        b.setFixed(bb);
3258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        cc = b.getFixed();
3268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(bb == cc);
3278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        cc = SkFixedMul(aa, bb);
3298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        c.setMul(a, b);
3308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkFixed dd = c.getFixed();
3318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int diff = cc - dd;
3328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(SkAbs32(diff) <= 1);
3338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fa = (float)aa / 65536.0f;
3358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fb = (float)bb / 65536.0f;
3368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        a.assertEquals(fa);
3378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        b.assertEquals(fb);
3388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fa = a.getFloat();
3398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fb = b.getFloat();
3408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        c.assertEquals(fa * fb, 1);
3428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        c.setDiv(a, b);
3448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        cc = SkFixedDiv(aa, bb);
3458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        dd = c.getFixed();
3468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        diff = cc - dd;
3478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(SkAbs32(diff) <= 3);
3488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        c.assertEquals(fa / fb, 1);
3508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT((aa == bb) == (a == b));
3528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT((aa != bb) == (a != b));
3538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT((aa < bb) == (a < b));
3548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT((aa <= bb) == (a <= b));
3558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT((aa > bb) == (a > b));
3568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT((aa >= bb) == (a >= b));
3578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (aa < 0)
3598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        {
3608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            aa = -aa;
3618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fa = -fa;
3628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
3638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        a.setFixed(aa);
3648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        c.setSqrt(a);
3658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        cc = SkFixedSqrt(aa);
3668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        dd = c.getFixed();
3678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(dd == cc);
3688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        c.assertEquals(sk_float_sqrt(fa), 2);
3708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // cuberoot
3728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#if 0
3738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        a.setInt(1);
3748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        a.cubeRoot();
3758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        a.assertEquals(1.0f, 0);
3768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        a.setInt(8);
3778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        a.cubeRoot();
3788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        a.assertEquals(2.0f, 0);
3798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        a.setInt(27);
3808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        a.cubeRoot();
3818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        a.assertEquals(3.0f, 0);
3828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
3838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
3858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
388