A game about forced loneliness, made by TACStudios
at master 145 lines 5.1 kB view raw
1using System; 2using System.Runtime.InteropServices; 3using Unity.Collections.LowLevel.Unsafe; 4using System.Diagnostics; 5 6namespace Unity.Collections 7{ 8 /// <summary> 9 /// An interface for a sequence of UTF-8 encoded text. 10 /// </summary> 11 public interface IUTF8Bytes 12 { 13 /// <summary> 14 /// Whether this IUTF8Bytes is empty. 15 /// </summary> 16 /// <value>True if this IUTF8Bytes is empty.</value> 17 bool IsEmpty { get; } 18 19 /// <summary> 20 /// Returns a pointer to the content of this IUTF8Bytes. 21 /// </summary> 22 /// <remarks>The pointer may point to stack memory.</remarks> 23 /// <returns>A pointer to the content of this IUTF8Bytes.</returns> 24 unsafe byte* GetUnsafePtr(); 25 26 /// <summary> 27 /// Attempt to set the length in bytes of this IUTF8Bytes's content buffer. 28 /// </summary> 29 /// <param name="newLength">The new length in bytes of the IUTF8Bytes's content buffer.</param> 30 /// <param name="clearOptions">Whether any bytes added should be zeroed out.</param> 31 /// <returns>True if the new length is valid.</returns> 32 bool TryResize(int newLength, NativeArrayOptions clearOptions = NativeArrayOptions.ClearMemory); 33 } 34 35 [GenerateTestsForBurstCompatibility] 36 internal unsafe static class FixedStringUtils 37 { 38 [StructLayout(LayoutKind.Explicit)] 39 internal struct UintFloatUnion 40 { 41 [FieldOffset(0)] 42 public uint uintValue; 43 [FieldOffset(0)] 44 public float floatValue; 45 } 46 47 internal static ParseError Base10ToBase2(ref float output, ulong mantissa10, int exponent10) 48 { 49 if (mantissa10 == 0) 50 { 51 output = 0.0f; 52 return ParseError.None; 53 } 54 if (exponent10 == 0) 55 { 56 output = mantissa10; 57 return ParseError.None; 58 } 59 var exponent2 = exponent10; 60 var mantissa2 = mantissa10; 61 while (exponent10 > 0) 62 { 63 while ((mantissa2 & 0xe000000000000000U) != 0) 64 { 65 mantissa2 >>= 1; 66 ++exponent2; 67 } 68 mantissa2 *= 5; 69 --exponent10; 70 } 71 while (exponent10 < 0) 72 { 73 while ((mantissa2 & 0x8000000000000000U) == 0) 74 { 75 mantissa2 <<= 1; 76 --exponent2; 77 } 78 mantissa2 /= 5; 79 ++exponent10; 80 } 81 // TODO: implement math.ldexpf (which presumably handles denormals (i don't)) 82 UintFloatUnion ufu = new UintFloatUnion(); 83 ufu.floatValue = mantissa2; 84 var e = (int)((ufu.uintValue >> 23) & 0xFFU) - 127; 85 e += exponent2; 86 if (e > 128) 87 return ParseError.Overflow; 88 if (e < -127) 89 return ParseError.Underflow; 90 ufu.uintValue = (ufu.uintValue & ~(0xFFU << 23)) | ((uint)(e + 127) << 23); 91 output = ufu.floatValue; 92 return ParseError.None; 93 } 94 95 internal static void Base2ToBase10(ref ulong mantissa10, ref int exponent10, float input) 96 { 97 UintFloatUnion ufu = new UintFloatUnion(); 98 ufu.floatValue = input; 99 if (ufu.uintValue == 0) 100 { 101 mantissa10 = 0; 102 exponent10 = 0; 103 return; 104 } 105 var mantissa2 = (ufu.uintValue & ((1 << 23) - 1)) | (1 << 23); 106 var exponent2 = (int)(ufu.uintValue >> 23) - 127 - 23; 107 mantissa10 = mantissa2; 108 exponent10 = exponent2; 109 if (exponent2 > 0) 110 { 111 while (exponent2 > 0) 112 { 113 // denormalize mantissa10 as much as you can, to minimize loss when doing /5 below. 114 while (mantissa10 <= UInt64.MaxValue / 10) 115 { 116 mantissa10 *= 10; 117 --exponent10; 118 } 119 mantissa10 /= 5; 120 --exponent2; 121 } 122 } 123 if (exponent2 < 0) 124 { 125 while (exponent2 < 0) 126 { 127 // normalize mantissa10 just as much as you need, in order to make the *5 below not overflow. 128 while (mantissa10 > UInt64.MaxValue / 5) 129 { 130 mantissa10 /= 10; 131 ++exponent10; 132 } 133 mantissa10 *= 5; 134 ++exponent2; 135 } 136 } 137 // normalize mantissa10 138 while (mantissa10 > 9999999U || mantissa10 % 10 == 0) 139 { 140 mantissa10 = (mantissa10 + (mantissa10 < 100000000U ? 5u : 0u)) / 10; 141 ++exponent10; 142 } 143 } 144 } 145}