Line data Source code
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 "SkHalf.h"
9 : #include "SkFloatBits.h"
10 :
11 0 : uint16_t halfMantissa(SkHalf h) {
12 0 : return h & 0x03ff;
13 : }
14 :
15 0 : uint16_t halfExponent(SkHalf h) {
16 0 : return (h >> 10) & 0x001f;
17 : }
18 :
19 0 : uint16_t halfSign(SkHalf h) {
20 0 : 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 0 : 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 0 : SkHalf o = 0;
37 :
38 : FloatUIntUnion floatUnion;
39 0 : floatUnion.fFloat = f;
40 :
41 0 : uint32_t sign = floatUnion.fUInt & sign_mask;
42 0 : 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 0 : if (floatUnion.fUInt >= f32infty)
51 : // NaN->qNaN and Inf->Inf
52 0 : o = (floatUnion.fUInt > f32infty) ? 0x7e00 : 0x7c00;
53 : // (De)normalized number or zero
54 : else {
55 0 : floatUnion.fUInt &= round_mask;
56 0 : floatUnion.fFloat *= magic.fFloat;
57 0 : floatUnion.fUInt -= round_mask;
58 : // Clamp to signed infinity if overflowed
59 0 : if (floatUnion.fUInt > f16infty) {
60 0 : floatUnion.fUInt = f16infty;
61 : }
62 :
63 0 : o = floatUnion.fUInt >> 13; // Take the bits!
64 : }
65 :
66 0 : o |= sign >> 16;
67 0 : 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 0 : float SkHalfToFloat(SkHalf h) {
73 : static const FloatUIntUnion magic = { 126 << 23 };
74 : FloatUIntUnion o;
75 :
76 0 : if (halfExponent(h) == 0)
77 : {
78 : // Zero / Denormal
79 0 : o.fUInt = magic.fUInt + halfMantissa(h);
80 0 : o.fFloat -= magic.fFloat;
81 : }
82 : else
83 : {
84 : // Set mantissa
85 0 : o.fUInt = halfMantissa(h) << 13;
86 : // Set exponent
87 0 : if (halfExponent(h) == 0x1f)
88 : // Inf/NaN
89 0 : o.fUInt |= (255 << 23);
90 : else
91 0 : o.fUInt |= ((127 - 15 + halfExponent(h)) << 23);
92 : }
93 :
94 : // Set sign
95 0 : o.fUInt |= (halfSign(h) << 31);
96 0 : return o.fFloat;
97 : }
|