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