A game about forced loneliness, made by TACStudios
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}