1685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com 2bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com/* 3685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * Copyright 2008 The Android Open Source Project 4bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com * 5685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * Use of this source code is governed by a BSD-style license that can be 6685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * found in the LICENSE file. 7bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com */ 8bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 9685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com 10bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkFloat.h" 111b03b2b8c46cc230a5f78a5617526d35da9fb29ereed@google.com#include "SkMathPriv.h" 12bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 13bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#define EXP_BIAS (127+23) 14bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 15bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comstatic int get_unsigned_exp(uint32_t packed) 16bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{ 17bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return (packed << 1 >> 24); 18bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 19bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 20bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comstatic unsigned get_unsigned_value(uint32_t packed) 21bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{ 22bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return (packed << 9 >> 9) | (1 << 23); 23bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 24bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 25bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comstatic int get_signed_value(int32_t packed) 26bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{ 27bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return SkApplySign(get_unsigned_value(packed), SkExtractSign(packed)); 28bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 29bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 30bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com///////////////////////////////////////////////////////////////////////// 31bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 32bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comint SkFloat::GetShift(int32_t packed, int shift) 33bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{ 34bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (packed == 0) 35bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return 0; 36bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 37bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int exp = get_unsigned_exp(packed) - EXP_BIAS - shift; 38bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int value = get_unsigned_value(packed); 39bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 40bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (exp >= 0) 41bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com { 42bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (exp > 8) // overflow 43bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com value = SK_MaxS32; 44bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com else 45bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com value <<= exp; 46bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 47bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com else 48bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com { 49bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com exp = -exp; 50bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (exp > 23) // underflow 51bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com value = 0; 52bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com else 53bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com value >>= exp; 54bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 55bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return SkApplySign(value, SkExtractSign(packed)); 56bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 57bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 58bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com///////////////////////////////////////////////////////////////////////////////////// 59bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 60bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comint32_t SkFloat::SetShift(int value, int shift) 61bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{ 62bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (value == 0) 63bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return 0; 64bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 65bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // record the sign and make value positive 66bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int sign = SkExtractSign(value); 67bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com value = SkApplySign(value, sign); 68bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 69bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (value >> 24) // value is too big (has more than 24 bits set) 70bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com { 71bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int bias = 8 - SkCLZ(value); 72bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(bias > 0 && bias < 8); 73bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com value >>= bias; 74bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com shift += bias; 75bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 76bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com else 77bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com { 78bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int zeros = SkCLZ(value << 8); 79bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(zeros >= 0 && zeros <= 23); 80bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com value <<= zeros; 81bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com shift -= zeros; 82bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 83bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // now value is left-aligned to 24 bits 84bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT((value >> 23) == 1); 85bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 86bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com shift += EXP_BIAS; 87bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (shift < 0) // underflow 88bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return 0; 89bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com else 90bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com { 91bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (shift > 255) // overflow 92bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com { 93bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com shift = 255; 94bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com value = 0x00FFFFFF; 95bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 96bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int32_t packed = sign << 31; // set the sign-bit 97bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com packed |= shift << 23; // store the packed exponent 98bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com packed |= ((unsigned)(value << 9) >> 9); // clear 24th bit of value (its implied) 99bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 100bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#ifdef SK_DEBUG 101bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com { 102bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int n; 103bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 104bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com n = SkExtractSign(packed); 105bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(n == sign); 106bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com n = get_unsigned_exp(packed); 107bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(n == shift); 108bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com n = get_unsigned_value(packed); 109bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(n == value); 110bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 111bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif 112bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return packed; 113bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 114bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 115bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 116bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comint32_t SkFloat::Neg(int32_t packed) 117bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{ 118bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (packed) 119bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com packed = packed ^ (1 << 31); 120bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return packed; 121bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 122bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 123bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comint32_t SkFloat::Add(int32_t packed_a, int32_t packed_b) 124bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{ 125bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (packed_a == 0) 126bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return packed_b; 127bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (packed_b == 0) 128bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return packed_a; 129bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 130bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int exp_a = get_unsigned_exp(packed_a); 131bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int exp_b = get_unsigned_exp(packed_b); 132bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int exp_diff = exp_a - exp_b; 133bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 134bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int shift_a = 0, shift_b = 0; 135bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int exp; 136bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 137bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (exp_diff >= 0) 138bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com { 139bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (exp_diff > 24) // B is too small to contribute 140bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return packed_a; 141bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com shift_b = exp_diff; 142bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com exp = exp_a; 143bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 144bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com else 145bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com { 146bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com exp_diff = -exp_diff; 147bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (exp_diff > 24) // A is too small to contribute 148bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return packed_b; 149bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com shift_a = exp_diff; 150bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com exp = exp_b; 151bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 152bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 153bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int value_a = get_signed_value(packed_a) >> shift_a; 154bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int value_b = get_signed_value(packed_b) >> shift_b; 155bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 156bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return SkFloat::SetShift(value_a + value_b, exp - EXP_BIAS); 157bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 158bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 159bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "Sk64.h" 160bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 161bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comstatic inline int32_t mul24(int32_t a, int32_t b) 162bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{ 163bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com Sk64 tmp; 164bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 165bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com tmp.setMul(a, b); 166bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com tmp.roundRight(24); 167bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return tmp.get32(); 168bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 169bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 170bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comint32_t SkFloat::Mul(int32_t packed_a, int32_t packed_b) 171bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{ 172bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (packed_a == 0 || packed_b == 0) 173bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return 0; 174bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 175bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int exp_a = get_unsigned_exp(packed_a); 176bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int exp_b = get_unsigned_exp(packed_b); 177bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 178bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int value_a = get_signed_value(packed_a); 179bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int value_b = get_signed_value(packed_b); 180bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 181bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return SkFloat::SetShift(mul24(value_a, value_b), exp_a + exp_b - 2*EXP_BIAS + 24); 182bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 183bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 184bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comint32_t SkFloat::MulInt(int32_t packed, int n) 185bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{ 186bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return Mul(packed, SetShift(n, 0)); 187bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 188bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 189bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comint32_t SkFloat::Div(int32_t packed_n, int32_t packed_d) 190bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{ 191bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(packed_d != 0); 192bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 193bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (packed_n == 0) 194bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return 0; 195bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 196bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int exp_n = get_unsigned_exp(packed_n); 197bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int exp_d = get_unsigned_exp(packed_d); 198bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 199bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int value_n = get_signed_value(packed_n); 200bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int value_d = get_signed_value(packed_d); 201bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 202bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return SkFloat::SetShift(SkDivBits(value_n, value_d, 24), exp_n - exp_d - 24); 203bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 204bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 205bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comint32_t SkFloat::DivInt(int32_t packed, int n) 206bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{ 207bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return Div(packed, SetShift(n, 0)); 208bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 209bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 210bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comint32_t SkFloat::Invert(int32_t packed) 211bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{ 212bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return Div(packed, SetShift(1, 0)); 213bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 214bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 215bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comint32_t SkFloat::Sqrt(int32_t packed) 216bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{ 217bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (packed < 0) 218bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com { 2192d7de2d243beab591671dfaf535a637b5d305735tomhudson@google.com SkDEBUGFAIL("can't sqrt a negative number"); 220bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return 0; 221bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 222bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 223bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int exp = get_unsigned_exp(packed); 224bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int value = get_unsigned_value(packed); 225bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 226bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int nexp = exp - EXP_BIAS; 227bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int root = SkSqrtBits(value << (nexp & 1), 26); 228bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com nexp >>= 1; 229bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return SkFloat::SetShift(root, nexp - 11); 230bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 231bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 232bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#if defined _WIN32 && _MSC_VER >= 1300 // disable warning : unreachable code 233bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#pragma warning ( push ) 234bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#pragma warning ( disable : 4702 ) 235bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif 236bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 237bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comint32_t SkFloat::CubeRoot(int32_t packed) 238bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{ 239bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com sk_throw(); 240bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return 0; 241bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 242bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 243bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#if defined _WIN32 && _MSC_VER >= 1300 244bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#pragma warning ( pop ) 245bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif 246bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 247bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comstatic inline int32_t clear_high_bit(int32_t n) 248bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{ 249bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return ((uint32_t)(n << 1)) >> 1; 250bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 251bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 252bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comstatic inline int int_sign(int32_t a, int32_t b) 253bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{ 254bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return a > b ? 1 : (a < b ? -1 : 0); 255bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 256bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 257bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comint SkFloat::Cmp(int32_t packed_a, int32_t packed_b) 258bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{ 259bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com packed_a = SkApplySign(clear_high_bit(packed_a), SkExtractSign(packed_a)); 260bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com packed_b = SkApplySign(clear_high_bit(packed_b), SkExtractSign(packed_b)); 261bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 262bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return int_sign(packed_a, packed_b); 263bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 264bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 265bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com///////////////////////////////////////////////////////////////////////////////////// 266bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com///////////////////////////////////////////////////////////////////////////////////// 267bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 268bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#ifdef SK_DEBUG 269bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 270bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkRandom.h" 2713dceba326fadf107085ff7c10e5fd56ba1715c09reed@google.com#include "SkFloatingPoint.h" 272bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 273bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkFloat::UnitTest() 274bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{ 275bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#ifdef SK_SUPPORT_UNITTEST 276bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkFloat a, b, c, d; 277bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int n; 278bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 279bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com a.setZero(); 280bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com n = a.getInt(); 281bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(n == 0); 282bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 283bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com b.setInt(5); 284bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com n = b.getInt(); 285bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(n == 5); 286bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 287bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com c.setInt(-3); 288bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com n = c.getInt(); 289bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(n == -3); 290bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 291bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com d.setAdd(c, b); 292935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com SkDebugf("SkFloat: %d + %d = %d\n", c.getInt(), b.getInt(), d.getInt()); 293bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 2941f875ad11f8302b5c0b136d2bb795b2f4c0707b3jvanverth@google.com SkMWCRandom rand; 295bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 296bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int i; 297bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com for (i = 0; i < 1000; i++) 298bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com { 299bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com float fa, fb; 300bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int aa = rand.nextS() >> 14; 301bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int bb = rand.nextS() >> 14; 302bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com a.setInt(aa); 303bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com b.setInt(bb); 304bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(a.getInt() == aa); 305bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(b.getInt() == bb); 306bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 307bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com c.setAdd(a, b); 308bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int cc = c.getInt(); 309bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(cc == aa + bb); 310bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 311bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com c.setSub(a, b); 312bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com cc = c.getInt(); 313bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(cc == aa - bb); 314bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 315bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com aa >>= 5; 316bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com bb >>= 5; 317bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com a.setInt(aa); 318bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com b.setInt(bb); 319bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com c.setMul(a, b); 320bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com cc = c.getInt(); 321bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(cc == aa * bb); 322bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com ///////////////////////////////////// 323bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 324bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com aa = rand.nextS() >> 11; 325bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com a.setFixed(aa); 326bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com cc = a.getFixed(); 327bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(aa == cc); 328bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 329bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com bb = rand.nextS() >> 11; 330bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com b.setFixed(bb); 331bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com cc = b.getFixed(); 332bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(bb == cc); 333bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 334bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com cc = SkFixedMul(aa, bb); 335bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com c.setMul(a, b); 336bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkFixed dd = c.getFixed(); 337bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int diff = cc - dd; 338bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(SkAbs32(diff) <= 1); 339bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 340bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fa = (float)aa / 65536.0f; 341bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fb = (float)bb / 65536.0f; 342bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com a.assertEquals(fa); 343bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com b.assertEquals(fb); 344bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fa = a.getFloat(); 345bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fb = b.getFloat(); 346bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 347bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com c.assertEquals(fa * fb, 1); 348bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 349bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com c.setDiv(a, b); 350bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com cc = SkFixedDiv(aa, bb); 351bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com dd = c.getFixed(); 352bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com diff = cc - dd; 353bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(SkAbs32(diff) <= 3); 354bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 355bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com c.assertEquals(fa / fb, 1); 356bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 357bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT((aa == bb) == (a == b)); 358bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT((aa != bb) == (a != b)); 359bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT((aa < bb) == (a < b)); 360bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT((aa <= bb) == (a <= b)); 361bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT((aa > bb) == (a > b)); 362bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT((aa >= bb) == (a >= b)); 363bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 364bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (aa < 0) 365bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com { 366bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com aa = -aa; 367bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fa = -fa; 368bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 369bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com a.setFixed(aa); 370bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com c.setSqrt(a); 371bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com cc = SkFixedSqrt(aa); 372bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com dd = c.getFixed(); 373bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(dd == cc); 374bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 375bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com c.assertEquals(sk_float_sqrt(fa), 2); 376bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 377bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // cuberoot 378bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#if 0 379bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com a.setInt(1); 380bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com a.cubeRoot(); 381bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com a.assertEquals(1.0f, 0); 382bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com a.setInt(8); 383bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com a.cubeRoot(); 384bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com a.assertEquals(2.0f, 0); 385bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com a.setInt(27); 386bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com a.cubeRoot(); 387bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com a.assertEquals(3.0f, 0); 388bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif 389bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 390bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif 391bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 392bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 393bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif 394