SkFloat.cpp revision ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976e
12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/*
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Copyright 2008 The Android Open Source Project
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Use of this source code is governed by a BSD-style license that can be
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * found in the LICENSE file.
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
94e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "SkFloat.h"
11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "SkMath.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define EXP_BIAS    (127+23)
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)static int get_unsigned_exp(uint32_t packed)
16a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles){
173240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    return (packed << 1 >> 24);
18eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
19eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static unsigned get_unsigned_value(uint32_t packed)
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return (packed << 9 >> 9) | (1 << 23);
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static int get_signed_value(int32_t packed)
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return SkApplySign(get_unsigned_value(packed), SkExtractSign(packed));
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/////////////////////////////////////////////////////////////////////////
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int SkFloat::GetShift(int32_t packed, int shift)
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (packed == 0)
354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        return 0;
364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    int exp = get_unsigned_exp(packed) - EXP_BIAS - shift;
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int value = get_unsigned_value(packed);
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (exp >= 0)
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (exp > 8)    // overflow
43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            value = SK_MaxS32;
4490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        else
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            value <<= exp;
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    else
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        exp = -exp;
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (exp > 23)   // underflow
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            value = 0;
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        else
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            value >>= exp;
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return SkApplySign(value, SkExtractSign(packed));
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/////////////////////////////////////////////////////////////////////////////////////
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int32_t SkFloat::SetShift(int value, int shift)
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (value == 0)
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return 0;
643240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // record the sign and make value positive
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int sign = SkExtractSign(value);
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    value = SkApplySign(value, sign);
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (value >> 24)    // value is too big (has more than 24 bits set)
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        int bias = 8 - SkCLZ(value);
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        SkASSERT(bias > 0 && bias < 8);
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        value >>= bias;
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        shift += bias;
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
7690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    else
7790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    {
7890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        int zeros = SkCLZ(value << 8);
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        SkASSERT(zeros >= 0 && zeros <= 23);
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        value <<= zeros;
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        shift -= zeros;
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // now value is left-aligned to 24 bits
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SkASSERT((value >> 23) == 1);
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    shift += EXP_BIAS;
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (shift < 0)  // underflow
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return 0;
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    else
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (shift > 255)    // overflow
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        {
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            shift = 255;
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            value = 0x00FFFFFF;
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        int32_t packed = sign << 31;        // set the sign-bit
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        packed |= shift << 23;          // store the packed exponent
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        packed |= ((unsigned)(value << 9) >> 9);    // clear 24th bit of value (its implied)
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#ifdef SK_DEBUG
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        {
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            int n;
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            n = SkExtractSign(packed);
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            SkASSERT(n == sign);
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            n = get_unsigned_exp(packed);
107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            SkASSERT(n == shift);
1083240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch            n = get_unsigned_value(packed);
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            SkASSERT(n == value);
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        }
111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return packed;
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int32_t SkFloat::Neg(int32_t packed)
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (packed)
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        packed = packed ^ (1 << 31);
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return packed;
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int32_t SkFloat::Add(int32_t packed_a, int32_t packed_b)
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (packed_a == 0)
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return packed_b;
127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (packed_b == 0)
12890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        return packed_a;
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int exp_a = get_unsigned_exp(packed_a);
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int exp_b = get_unsigned_exp(packed_b);
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int exp_diff = exp_a - exp_b;
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int shift_a = 0, shift_b = 0;
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int exp;
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (exp_diff >= 0)
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (exp_diff > 24)  // B is too small to contribute
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            return packed_a;
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        shift_b = exp_diff;
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        exp = exp_a;
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
14490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    else
14590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    {
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        exp_diff = -exp_diff;
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (exp_diff > 24)  // A is too small to contribute
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            return packed_b;
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        shift_a = exp_diff;
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        exp = exp_b;
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int value_a = get_signed_value(packed_a) >> shift_a;
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int value_b = get_signed_value(packed_b) >> shift_b;
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return SkFloat::SetShift(value_a + value_b, exp - EXP_BIAS);
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "Sk64.h"
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static inline int32_t mul24(int32_t a, int32_t b)
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Sk64 tmp;
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    tmp.setMul(a, b);
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    tmp.roundRight(24);
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return tmp.get32();
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int32_t SkFloat::Mul(int32_t packed_a, int32_t packed_b)
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (packed_a == 0 || packed_b == 0)
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return 0;
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int exp_a = get_unsigned_exp(packed_a);
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int exp_b = get_unsigned_exp(packed_b);
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int value_a = get_signed_value(packed_a);
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int value_b = get_signed_value(packed_b);
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return SkFloat::SetShift(mul24(value_a, value_b), exp_a + exp_b - 2*EXP_BIAS + 24);
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int32_t SkFloat::MulInt(int32_t packed, int n)
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Mul(packed, SetShift(n, 0));
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int32_t SkFloat::Div(int32_t packed_n, int32_t packed_d)
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SkASSERT(packed_d != 0);
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (packed_n == 0)
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return 0;
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int exp_n = get_unsigned_exp(packed_n);
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int exp_d = get_unsigned_exp(packed_d);
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int value_n = get_signed_value(packed_n);
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int value_d = get_signed_value(packed_d);
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return SkFloat::SetShift(SkDivBits(value_n, value_d, 24), exp_n - exp_d - 24);
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int32_t SkFloat::DivInt(int32_t packed, int n)
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Div(packed, SetShift(n, 0));
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int32_t SkFloat::Invert(int32_t packed)
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Div(packed, SetShift(1, 0));
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int32_t SkFloat::Sqrt(int32_t packed)
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (packed < 0)
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        SkASSERT(!"can't sqrt a negative number");
220c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return 0;
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int exp = get_unsigned_exp(packed);
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int value = get_unsigned_value(packed);
225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int nexp = exp - EXP_BIAS;
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int root = SkSqrtBits(value << (nexp & 1), 26);
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    nexp >>= 1;
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return SkFloat::SetShift(root, nexp - 11);
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined _WIN32 && _MSC_VER >= 1300  // disable warning : unreachable code
233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#pragma warning ( push )
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#pragma warning ( disable : 4702 )
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int32_t SkFloat::CubeRoot(int32_t packed)
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sk_throw();
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return 0;
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined _WIN32 && _MSC_VER >= 1300
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#pragma warning ( pop )
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static inline int32_t clear_high_bit(int32_t n)
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return ((uint32_t)(n << 1)) >> 1;
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static inline int int_sign(int32_t a, int32_t b)
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return a > b ? 1 : (a < b ? -1 : 0);
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int SkFloat::Cmp(int32_t packed_a, int32_t packed_b)
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    packed_a = SkApplySign(clear_high_bit(packed_a), SkExtractSign(packed_a));
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    packed_b = SkApplySign(clear_high_bit(packed_b), SkExtractSign(packed_b));
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return int_sign(packed_a, packed_b);
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/////////////////////////////////////////////////////////////////////////////////////
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/////////////////////////////////////////////////////////////////////////////////////
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
268c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#ifdef SK_DEBUG
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "SkRandom.h"
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#ifdef SK_CAN_USE_FLOAT
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    #include "SkFloatingPoint.h"
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SkFloat::UnitTest()
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#ifdef SK_SUPPORT_UNITTEST
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SkFloat a, b, c, d;
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int     n;
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    a.setZero();
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    n = a.getInt();
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SkASSERT(n == 0);
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    b.setInt(5);
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    n = b.getInt();
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SkASSERT(n == 5);
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    c.setInt(-3);
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    n = c.getInt();
2914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    SkASSERT(n == -3);
2924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    d.setAdd(c, b);
2944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    SkDebugf("SkFloat: %d + %d = %d\n", c.getInt(), b.getInt(), d.getInt());
2954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    SkRandom    rand;
2974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#ifdef SK_CAN_USE_FLOAT
2994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    int i;
3004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    for (i = 0; i < 1000; i++)
3014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    {
3024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        float fa, fb;
3034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        int aa = rand.nextS() >> 14;
3044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        int bb = rand.nextS() >> 14;
3054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        a.setInt(aa);
306a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        b.setInt(bb);
307a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        SkASSERT(a.getInt() == aa);
308a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        SkASSERT(b.getInt() == bb);
309a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
310a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        c.setAdd(a, b);
311a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        int cc = c.getInt();
312a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        SkASSERT(cc == aa + bb);
313a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
314a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        c.setSub(a, b);
315a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        cc = c.getInt();
316f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        SkASSERT(cc == aa - bb);
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        aa >>= 5;
319f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        bb >>= 5;
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        a.setInt(aa);
321c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        b.setInt(bb);
322c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        c.setMul(a, b);
323        cc = c.getInt();
324        SkASSERT(cc == aa * bb);
325        /////////////////////////////////////
326
327        aa = rand.nextS() >> 11;
328        a.setFixed(aa);
329        cc = a.getFixed();
330        SkASSERT(aa == cc);
331
332        bb = rand.nextS() >> 11;
333        b.setFixed(bb);
334        cc = b.getFixed();
335        SkASSERT(bb == cc);
336
337        cc = SkFixedMul(aa, bb);
338        c.setMul(a, b);
339        SkFixed dd = c.getFixed();
340        int diff = cc - dd;
341        SkASSERT(SkAbs32(diff) <= 1);
342
343        fa = (float)aa / 65536.0f;
344        fb = (float)bb / 65536.0f;
345        a.assertEquals(fa);
346        b.assertEquals(fb);
347        fa = a.getFloat();
348        fb = b.getFloat();
349
350        c.assertEquals(fa * fb, 1);
351
352        c.setDiv(a, b);
353        cc = SkFixedDiv(aa, bb);
354        dd = c.getFixed();
355        diff = cc - dd;
356        SkASSERT(SkAbs32(diff) <= 3);
357
358        c.assertEquals(fa / fb, 1);
359
360        SkASSERT((aa == bb) == (a == b));
361        SkASSERT((aa != bb) == (a != b));
362        SkASSERT((aa < bb) == (a < b));
363        SkASSERT((aa <= bb) == (a <= b));
364        SkASSERT((aa > bb) == (a > b));
365        SkASSERT((aa >= bb) == (a >= b));
366
367        if (aa < 0)
368        {
369            aa = -aa;
370            fa = -fa;
371        }
372        a.setFixed(aa);
373        c.setSqrt(a);
374        cc = SkFixedSqrt(aa);
375        dd = c.getFixed();
376        SkASSERT(dd == cc);
377
378        c.assertEquals(sk_float_sqrt(fa), 2);
379
380        // cuberoot
381#if 0
382        a.setInt(1);
383        a.cubeRoot();
384        a.assertEquals(1.0f, 0);
385        a.setInt(8);
386        a.cubeRoot();
387        a.assertEquals(2.0f, 0);
388        a.setInt(27);
389        a.cubeRoot();
390        a.assertEquals(3.0f, 0);
391#endif
392    }
393#endif
394#endif
395}
396
397#endif
398