1 | /* |
---|---|
2 | * Copyright 2014 Google Inc. |
3 | * |
4 | * Use of this source code is governed by a BSD-style license that can be |
5 | * found in the LICENSE file. |
6 | */ |
7 | |
8 | #include "include/private/SkFloatBits.h" |
9 | #include "include/private/SkHalf.h" |
10 | |
11 | uint16_t halfMantissa(SkHalf h) { |
12 | return h & 0x03ff; |
13 | } |
14 | |
15 | uint16_t halfExponent(SkHalf h) { |
16 | return (h >> 10) & 0x001f; |
17 | } |
18 | |
19 | uint16_t halfSign(SkHalf h) { |
20 | return h >> 15; |
21 | } |
22 | |
23 | union FloatUIntUnion { |
24 | uint32_t fUInt; // this must come first for the initializations below to work |
25 | float fFloat; |
26 | }; |
27 | |
28 | // based on Fabien Giesen's float_to_half_fast3() |
29 | // see https://gist.github.com/rygorous/2156668 |
30 | SkHalf SkFloatToHalf(float f) { |
31 | static const uint32_t f32infty = { 255 << 23 }; |
32 | static const uint32_t f16infty = { 31 << 23 }; |
33 | static const FloatUIntUnion magic = { 15 << 23 }; |
34 | static const uint32_t sign_mask = 0x80000000u; |
35 | static const uint32_t round_mask = ~0xfffu; |
36 | SkHalf o = 0; |
37 | |
38 | FloatUIntUnion floatUnion; |
39 | floatUnion.fFloat = f; |
40 | |
41 | uint32_t sign = floatUnion.fUInt & sign_mask; |
42 | floatUnion.fUInt ^= sign; |
43 | |
44 | // NOTE all the integer compares in this function can be safely |
45 | // compiled into signed compares since all operands are below |
46 | // 0x80000000. Important if you want fast straight SSE2 code |
47 | // (since there's no unsigned PCMPGTD). |
48 | |
49 | // Inf or NaN (all exponent bits set) |
50 | if (floatUnion.fUInt >= f32infty) |
51 | // NaN->qNaN and Inf->Inf |
52 | o = (floatUnion.fUInt > f32infty) ? 0x7e00 : 0x7c00; |
53 | // (De)normalized number or zero |
54 | else { |
55 | floatUnion.fUInt &= round_mask; |
56 | floatUnion.fFloat *= magic.fFloat; |
57 | floatUnion.fUInt -= round_mask; |
58 | // Clamp to signed infinity if overflowed |
59 | if (floatUnion.fUInt > f16infty) { |
60 | floatUnion.fUInt = f16infty; |
61 | } |
62 | |
63 | o = floatUnion.fUInt >> 13; // Take the bits! |
64 | } |
65 | |
66 | o |= sign >> 16; |
67 | return o; |
68 | } |
69 | |
70 | // based on Fabien Giesen's half_to_float_fast2() |
71 | // see https://fgiesen.wordpress.com/2012/03/28/half-to-float-done-quic/ |
72 | float SkHalfToFloat(SkHalf h) { |
73 | static const FloatUIntUnion magic = { 126 << 23 }; |
74 | FloatUIntUnion o; |
75 | |
76 | if (halfExponent(h) == 0) |
77 | { |
78 | // Zero / Denormal |
79 | o.fUInt = magic.fUInt + halfMantissa(h); |
80 | o.fFloat -= magic.fFloat; |
81 | } |
82 | else |
83 | { |
84 | // Set mantissa |
85 | o.fUInt = halfMantissa(h) << 13; |
86 | // Set exponent |
87 | if (halfExponent(h) == 0x1f) |
88 | // Inf/NaN |
89 | o.fUInt |= (255 << 23); |
90 | else |
91 | o.fUInt |= ((127 - 15 + halfExponent(h)) << 23); |
92 | } |
93 | |
94 | // Set sign |
95 | o.fUInt |= (halfSign(h) << 31); |
96 | return o.fFloat; |
97 | } |
98 |