SkHalf.cpp 2.6 KB

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