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