• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  
halfMantissa(SkHalf h)11  uint16_t halfMantissa(SkHalf h) {
12      return h & 0x03ff;
13  }
14  
halfExponent(SkHalf h)15  uint16_t halfExponent(SkHalf h) {
16      return (h >> 10) & 0x001f;
17  }
18  
halfSign(SkHalf h)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
SkFloatToHalf(float f)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/
SkHalfToFloat(SkHalf h)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