Без опису
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. #if BURST_INTERNAL || UNITY_BURST_EXPERIMENTAL_NEON_INTRINSICS
  2. using System.Runtime.CompilerServices;
  3. using System.Runtime.InteropServices;
  4. using static Unity.Burst.Intrinsics.Arm.Neon;
  5. using static Unity.Burst.Intrinsics.X86.F16C;
  6. namespace Unity.Burst.Intrinsics
  7. {
  8. /// <summary>
  9. /// Represents a 16-bit floating point value (half precision)
  10. /// Warning: this type may not be natively supported by your hardware, or its usage may be suboptimal
  11. /// </summary>
  12. public readonly struct f16 : System.IEquatable<f16>
  13. {
  14. /// <summary>
  15. /// The container for the actual 16-bit half precision floating point value
  16. /// </summary>
  17. private readonly ushort value;
  18. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  19. private static uint f32tof16(float x)
  20. {
  21. if (IsF16CSupported)
  22. {
  23. var v = new v128();
  24. v.Float0 = x;
  25. var result = cvtps_ph(v, (int)X86.RoundingMode.FROUND_TRUNC_NOEXC);
  26. return result.UShort0;
  27. }
  28. else if (IsNeonHalfFPSupported)
  29. {
  30. var v = new v128();
  31. v.Float0 = x;
  32. var result = vcvt_f16_f32(v);
  33. return result.UShort0;
  34. }
  35. // Managed fallback
  36. const int infinity_32 = 255 << 23;
  37. const uint msk = 0x7FFFF000u;
  38. uint ux = asuint(x);
  39. uint uux = ux & msk;
  40. uint h = (uint)(asuint(min(asfloat(uux) * 1.92592994e-34f, 260042752.0f)) + 0x1000) >> 13; // Clamp to signed infinity if overflowed
  41. h = select(h,
  42. select(0x7c00u, 0x7e00u, (int)uux > infinity_32),
  43. (int)uux >= infinity_32); // NaN->qNaN and Inf->Inf
  44. return h | (ux & ~msk) >> 16;
  45. }
  46. /// <summary>Returns the bit pattern of a float as a uint.</summary>
  47. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  48. private static uint asuint(float x) { return (uint)asint(x); }
  49. /// <summary>Returns the minimum of two float values.</summary>
  50. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  51. private static float min(float x, float y) { return float.IsNaN(y) || x < y ? x : y; }
  52. /// <summary>Returns b if c is true, a otherwise.</summary>
  53. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  54. private static uint select(uint a, uint b, bool c) { return c ? b : a; }
  55. /// <summary>Returns the bit pattern of a uint as a float.</summary>
  56. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  57. private static float asfloat(uint x) { return asfloat((int)x); }
  58. [StructLayout(LayoutKind.Explicit)]
  59. private struct IntFloatUnion
  60. {
  61. [FieldOffset(0)]
  62. public int intValue;
  63. [FieldOffset(0)]
  64. public float floatValue;
  65. }
  66. /// <summary>Returns the bit pattern of an int as a float.</summary>
  67. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  68. private static float asfloat(int x)
  69. {
  70. IntFloatUnion u;
  71. u.floatValue = 0;
  72. u.intValue = x;
  73. return u.floatValue;
  74. }
  75. /// <summary>Returns the bit pattern of a float as an int.</summary>
  76. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  77. private static int asint(float x)
  78. {
  79. IntFloatUnion u;
  80. u.intValue = 0;
  81. u.floatValue = x;
  82. return u.intValue;
  83. }
  84. /// <summary>Constructs a half value from a half value.</summary>
  85. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  86. public f16(f16 x)
  87. {
  88. value = x.value;
  89. }
  90. /// <summary>Constructs a half value from a float value.</summary>
  91. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  92. public f16(float v)
  93. {
  94. value = (ushort)f32tof16(v);
  95. }
  96. /// <summary>Returns whether two f16 values are equal.</summary>
  97. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  98. public static bool operator ==(f16 lhs, f16 rhs)
  99. {
  100. return lhs.value == rhs.value;
  101. }
  102. /// <summary>Returns whether two f16 values are different.</summary>
  103. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  104. public static bool operator !=(f16 lhs, f16 rhs)
  105. {
  106. return lhs.value != rhs.value;
  107. }
  108. /// <summary>Returns true if the f16 is equal to a given f16, false otherwise.</summary>
  109. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  110. public bool Equals(f16 rhs)
  111. {
  112. return value == rhs.value;
  113. }
  114. /// <summary>Returns true if the half is equal to a given half, false otherwise.</summary>
  115. public override bool Equals(object o) { return Equals((f16)o); }
  116. /// <summary>Returns a hash code for the half.</summary>
  117. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  118. public override int GetHashCode() { return (int)value; }
  119. }
  120. }
  121. #endif // BURST_INTERNAL || UNITY_BURST_EXPERIMENTAL_NEON_INTRINSICS