public static unsafe float HalfToFloat(ushort value) { const ushort ExponentMask = 0x7C00; const ushort ExponentShift = 10; const ushort SignificandMask = 0x03FF; const ushort SignificandShift = 0; const ushort MaxExponent = 0x1F; bool sign = (short)value < 0; int exp = (sbyte)((value & ExponentMask) >> ExponentShift); uint sig = (ushort)((value & SignificandMask) >> SignificandShift); if (exp == MaxExponent) { if (sig != 0) { return(CreateSingleNaN(sign, (ulong)sig << 54)); } return(sign ? float.NegativeInfinity : float.PositiveInfinity); } if (exp == 0) { if (sig == 0) { return(CborHelpers.UInt32BitsToSingle(sign ? FloatSignMask : 0)); // Positive / Negative zero } (exp, sig) = NormSubnormalF16Sig(sig); exp -= 1; } return(CreateSingle(sign, (byte)(exp + 0x70), sig << 13));
/// <summary>Reads the next data item as a double-precision floating point number (major type 7).</summary> /// <returns>The decoded <see cref="double" /> value.</returns> /// <exception cref="InvalidOperationException"><para>The next data item does not have the correct major type.</para> /// <para>-or-</para> /// <para>The next simple value is not a floating-point number encoding.</para></exception> /// <exception cref="CborContentException"><para>The next value has an invalid CBOR encoding.</para> /// <para>-or-</para> /// <para>There was an unexpected end of CBOR encoding data.</para> /// <para>-or-</para> /// <para>The next value uses a CBOR encoding that is not valid under the current conformance mode.</para></exception> public double ReadDouble() { CborInitialByte header = PeekInitialByte(expectedType: CborMajorType.Simple); ReadOnlySpan <byte> buffer = GetRemainingBytes(); double result; switch (header.AdditionalInfo) { case CborAdditionalInfo.Additional16BitData: EnsureReadCapacity(buffer, 1 + sizeof(short)); result = HalfHelpers.HalfToDouble(CborHelpers.ReadHalfBigEndian(buffer.Slice(1))); AdvanceBuffer(1 + sizeof(short)); AdvanceDataItemCounters(); return(result); case CborAdditionalInfo.Additional32BitData: EnsureReadCapacity(buffer, 1 + sizeof(float)); result = CborHelpers.ReadSingleBigEndian(buffer.Slice(1)); AdvanceBuffer(1 + sizeof(float)); AdvanceDataItemCounters(); return(result); case CborAdditionalInfo.Additional64BitData: EnsureReadCapacity(buffer, 1 + sizeof(double)); result = CborHelpers.ReadDoubleBigEndian(buffer.Slice(1)); AdvanceBuffer(1 + sizeof(double)); AdvanceDataItemCounters(); return(result); default: throw new InvalidOperationException(SR.Cbor_Reader_NotAFloatEncoding); } }
private void WriteDoubleCore(double value) { EnsureWriteCapacity(1 + sizeof(double)); WriteInitialByte(new CborInitialByte(CborMajorType.Simple, CborAdditionalInfo.Additional64BitData)); CborHelpers.WriteDoubleBigEndian(_buffer.AsSpan(_offset), value); _offset += sizeof(double); AdvanceDataItemCounters(); }
/// <summary>Writes the provided value as a tagged bignum encoding, as described in RFC7049 section 2.4.2.</summary> /// <param name="value">The value to write.</param> /// <exception cref="InvalidOperationException"><para>Writing a new value exceeds the definite length of the parent data item.</para> /// <para>-or-</para> /// <para>The major type of the encoded value is not permitted in the parent data item.</para> /// <para>-or-</para> /// <para>The written data is not accepted under the current conformance mode.</para></exception> public void WriteBigInteger(BigInteger value) { bool isUnsigned = value.Sign >= 0; BigInteger unsignedValue = isUnsigned ? value : -1 - value; byte[] unsignedBigEndianEncoding = CborHelpers.CreateUnsignedBigEndianBytesFromBigInteger(unsignedValue); WriteTag(isUnsigned ? CborTag.UnsignedBigNum : CborTag.NegativeBigNum); WriteByteString(unsignedBigEndianEncoding); }
/// reconstructs a decimal value out of a signed integral component and a negative base-10 exponent private static decimal ReconstructFromNegativeScale(decimal mantissa, byte scale) { Span <int> buf = stackalloc int[4]; CborHelpers.GetBitsFromDecimal(mantissa, buf); int flags = buf[3]; bool isNegative = (flags & SignMask) == SignMask; Debug.Assert((flags & ScaleMask) == 0, "mantissa argument should be integral."); return(new decimal(lo: buf[0], mid: buf[1], hi: buf[2], isNegative: isNegative, scale: scale)); }
/// deconstructs a decimal value into its signed integral component and negative base-10 exponent public static void Deconstruct(decimal value, out decimal mantissa, out byte scale) { Span <int> buf = stackalloc int[4]; CborHelpers.GetBitsFromDecimal(value, buf); int flags = buf[3]; bool isNegative = (flags & SignMask) == SignMask; mantissa = new decimal(lo: buf[0], mid: buf[1], hi: buf[2], isNegative: isNegative, scale: 0); scale = (byte)((flags & ScaleMask) >> ScaleShift); }
static float CreateSingle(bool sign, byte exp, uint sig) => CborHelpers.Int32BitsToSingle((int)(((sign ? 1U : 0U) << FloatSignShift) + ((uint)exp << FloatExponentShift) + sig));
internal static bool TryConvertSingleToHalf(float value, out ushort result) { result = HalfHelpers.FloatToHalf(value); return(CborHelpers.SingleToInt32Bits(HalfHelpers.HalfToFloat(result)) == CborHelpers.SingleToInt32Bits(value)); }