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