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