123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145 |
- using System;
- using System.Runtime.InteropServices;
- using Unity.Collections.LowLevel.Unsafe;
- using System.Diagnostics;
-
- namespace Unity.Collections
- {
- /// <summary>
- /// An interface for a sequence of UTF-8 encoded text.
- /// </summary>
- public interface IUTF8Bytes
- {
- /// <summary>
- /// Whether this IUTF8Bytes is empty.
- /// </summary>
- /// <value>True if this IUTF8Bytes is empty.</value>
- bool IsEmpty { get; }
-
- /// <summary>
- /// Returns a pointer to the content of this IUTF8Bytes.
- /// </summary>
- /// <remarks>The pointer may point to stack memory.</remarks>
- /// <returns>A pointer to the content of this IUTF8Bytes.</returns>
- unsafe byte* GetUnsafePtr();
-
- /// <summary>
- /// Attempt to set the length in bytes of this IUTF8Bytes's content buffer.
- /// </summary>
- /// <param name="newLength">The new length in bytes of the IUTF8Bytes's content buffer.</param>
- /// <param name="clearOptions">Whether any bytes added should be zeroed out.</param>
- /// <returns>True if the new length is valid.</returns>
- bool TryResize(int newLength, NativeArrayOptions clearOptions = NativeArrayOptions.ClearMemory);
- }
-
- [GenerateTestsForBurstCompatibility]
- internal unsafe static class FixedStringUtils
- {
- [StructLayout(LayoutKind.Explicit)]
- internal struct UintFloatUnion
- {
- [FieldOffset(0)]
- public uint uintValue;
- [FieldOffset(0)]
- public float floatValue;
- }
-
- internal static ParseError Base10ToBase2(ref float output, ulong mantissa10, int exponent10)
- {
- if (mantissa10 == 0)
- {
- output = 0.0f;
- return ParseError.None;
- }
- if (exponent10 == 0)
- {
- output = mantissa10;
- return ParseError.None;
- }
- var exponent2 = exponent10;
- var mantissa2 = mantissa10;
- while (exponent10 > 0)
- {
- while ((mantissa2 & 0xe000000000000000U) != 0)
- {
- mantissa2 >>= 1;
- ++exponent2;
- }
- mantissa2 *= 5;
- --exponent10;
- }
- while (exponent10 < 0)
- {
- while ((mantissa2 & 0x8000000000000000U) == 0)
- {
- mantissa2 <<= 1;
- --exponent2;
- }
- mantissa2 /= 5;
- ++exponent10;
- }
- // TODO: implement math.ldexpf (which presumably handles denormals (i don't))
- UintFloatUnion ufu = new UintFloatUnion();
- ufu.floatValue = mantissa2;
- var e = (int)((ufu.uintValue >> 23) & 0xFFU) - 127;
- e += exponent2;
- if (e > 128)
- return ParseError.Overflow;
- if (e < -127)
- return ParseError.Underflow;
- ufu.uintValue = (ufu.uintValue & ~(0xFFU << 23)) | ((uint)(e + 127) << 23);
- output = ufu.floatValue;
- return ParseError.None;
- }
-
- internal static void Base2ToBase10(ref ulong mantissa10, ref int exponent10, float input)
- {
- UintFloatUnion ufu = new UintFloatUnion();
- ufu.floatValue = input;
- if (ufu.uintValue == 0)
- {
- mantissa10 = 0;
- exponent10 = 0;
- return;
- }
- var mantissa2 = (ufu.uintValue & ((1 << 23) - 1)) | (1 << 23);
- var exponent2 = (int)(ufu.uintValue >> 23) - 127 - 23;
- mantissa10 = mantissa2;
- exponent10 = exponent2;
- if (exponent2 > 0)
- {
- while (exponent2 > 0)
- {
- // denormalize mantissa10 as much as you can, to minimize loss when doing /5 below.
- while (mantissa10 <= UInt64.MaxValue / 10)
- {
- mantissa10 *= 10;
- --exponent10;
- }
- mantissa10 /= 5;
- --exponent2;
- }
- }
- if (exponent2 < 0)
- {
- while (exponent2 < 0)
- {
- // normalize mantissa10 just as much as you need, in order to make the *5 below not overflow.
- while (mantissa10 > UInt64.MaxValue / 5)
- {
- mantissa10 /= 10;
- ++exponent10;
- }
- mantissa10 *= 5;
- ++exponent2;
- }
- }
- // normalize mantissa10
- while (mantissa10 > 9999999U || mantissa10 % 10 == 0)
- {
- mantissa10 = (mantissa10 + (mantissa10 < 100000000U ? 5u : 0u)) / 10;
- ++exponent10;
- }
- }
- }
- }
|