CryHalf.inl 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #ifndef CRY_HALF_INL
  9. #define CRY_HALF_INL
  10. #pragma once
  11. typedef uint16 CryHalf;
  12. typedef union floatint_union
  13. {
  14. float f;
  15. uint32 i;
  16. } floatint_union;
  17. __forceinline CryHalf CryConvertFloatToHalf(const float Value)
  18. {
  19. #if defined(LINUX) || defined(MAC)
  20. asm volatile("" ::: "memory");
  21. #endif
  22. unsigned int Result;
  23. unsigned int IValue = ((unsigned int*)(&Value))[0];
  24. unsigned int Sign = (IValue & 0x80000000U) >> 16U;
  25. IValue = IValue & 0x7FFFFFFFU; // Hack off the sign
  26. if (IValue > 0x47FFEFFFU)
  27. {
  28. // The number is too large to be represented as a half. Saturate to infinity.
  29. Result = 0x7FFFU;
  30. }
  31. else
  32. {
  33. if (IValue < 0x38800000U)
  34. {
  35. // The number is too small to be represented as a normalized half.
  36. // Convert it to a denormalized value.
  37. unsigned int Shift = 113U - (IValue >> 23U);
  38. IValue = (0x800000U | (IValue & 0x7FFFFFU)) >> Shift;
  39. }
  40. else
  41. {
  42. // Rebias the exponent to represent the value as a normalized half.
  43. IValue += 0xC8000000U;
  44. }
  45. Result = ((IValue + 0x0FFFU + ((IValue >> 13U) & 1U)) >> 13U) & 0x7FFFU;
  46. }
  47. return (CryHalf)(Result | Sign);
  48. }
  49. __forceinline float CryConvertHalfToFloat(const CryHalf Value)
  50. {
  51. #if defined(LINUX) || defined(MAC)
  52. asm volatile("" ::: "memory");
  53. #endif
  54. unsigned int Mantissa;
  55. unsigned int Exponent;
  56. unsigned int Result;
  57. Mantissa = (unsigned int)(Value & 0x03FF);
  58. if ((Value & 0x7C00) != 0) // The value is normalized
  59. {
  60. Exponent = (unsigned int)((Value >> 10) & 0x1F);
  61. }
  62. else if (Mantissa != 0) // The value is denormalized
  63. {
  64. // Normalize the value in the resulting float
  65. Exponent = 1;
  66. do
  67. {
  68. Exponent--;
  69. Mantissa <<= 1;
  70. } while ((Mantissa & 0x0400) == 0);
  71. Mantissa &= 0x03FF;
  72. }
  73. else // The value is zero
  74. {
  75. Exponent = (unsigned int)-112;
  76. }
  77. Result = ((Value & 0x8000) << 16) | // Sign
  78. ((Exponent + 112) << 23) | // Exponent
  79. (Mantissa << 13); // Mantissa
  80. return *(float*)&Result;
  81. }
  82. struct CryHalf2
  83. {
  84. CryHalf x;
  85. CryHalf y;
  86. CryHalf2()
  87. {
  88. }
  89. CryHalf2(CryHalf _x, CryHalf _y)
  90. : x(_x)
  91. , y(_y)
  92. {
  93. }
  94. CryHalf2(const CryHalf* const __restrict pArray)
  95. {
  96. x = pArray[0];
  97. y = pArray[1];
  98. }
  99. CryHalf2(float _x, float _y)
  100. {
  101. x = CryConvertFloatToHalf(_x);
  102. y = CryConvertFloatToHalf(_y);
  103. }
  104. CryHalf2(const float* const __restrict pArray)
  105. {
  106. x = CryConvertFloatToHalf(pArray[0]);
  107. y = CryConvertFloatToHalf(pArray[1]);
  108. }
  109. CryHalf2& operator= (const CryHalf2& Half2)
  110. {
  111. x = Half2.x;
  112. y = Half2.y;
  113. return *this;
  114. }
  115. bool operator !=(const CryHalf2& rhs) const
  116. {
  117. return x != rhs.x || y != rhs.y;
  118. }
  119. };
  120. struct CryHalf4
  121. {
  122. CryHalf x;
  123. CryHalf y;
  124. CryHalf z;
  125. CryHalf w;
  126. CryHalf4()
  127. {
  128. }
  129. CryHalf4(CryHalf _x, CryHalf _y, CryHalf _z, CryHalf _w)
  130. : x(_x)
  131. , y(_y)
  132. , z(_z)
  133. , w(_w)
  134. {
  135. }
  136. CryHalf4(const CryHalf* const __restrict pArray)
  137. {
  138. x = pArray[0];
  139. y = pArray[1];
  140. z = pArray[2];
  141. w = pArray[3];
  142. }
  143. CryHalf4(float _x, float _y, float _z, float _w)
  144. {
  145. x = CryConvertFloatToHalf(_x);
  146. y = CryConvertFloatToHalf(_y);
  147. z = CryConvertFloatToHalf(_z);
  148. w = CryConvertFloatToHalf(_w);
  149. }
  150. CryHalf4(const float* const __restrict pArray)
  151. {
  152. x = CryConvertFloatToHalf(pArray[0]);
  153. y = CryConvertFloatToHalf(pArray[1]);
  154. z = CryConvertFloatToHalf(pArray[2]);
  155. w = CryConvertFloatToHalf(pArray[3]);
  156. }
  157. CryHalf4& operator= (const CryHalf4& Half4)
  158. {
  159. x = Half4.x;
  160. y = Half4.y;
  161. z = Half4.z;
  162. w = Half4.w;
  163. return *this;
  164. }
  165. bool operator !=(const CryHalf4& rhs) const
  166. {
  167. return x != rhs.x || y != rhs.y || z != rhs.z || w != rhs.w;
  168. }
  169. };
  170. #endif // #ifndef CRY_HALF_INL