Exemplo n.º 1
0
        public float ReadHalf()
        {
            var encoded = ReadUInt16();

            // Decode half float
            // Based on numpy implementation (https://github.com/numpy/numpy/blob/984bc91367f9b525eadef14c48c759999bc4adfc/numpy/core/src/npymath/halffloat.c#L477)
            uint decoded;
            uint halfExponent = (encoded & 0x7c00u);
            uint singleSign   = (encoded & 0x8000u) << 16;

            switch (halfExponent)
            {
            case 0x0000u:     /* 0 or subnormal */
                uint halfSign = (encoded & 0x03ffu);

                if (halfSign == 0)
                {
                    /* Signed zero */
                    decoded = singleSign;
                }
                else
                {
                    /* Subnormal */
                    halfSign <<= 1;

                    while ((halfSign & 0x0400u) == 0)
                    {
                        halfSign <<= 1;
                        halfExponent++;
                    }

                    uint singleExponent = 127 - 15 - halfExponent << 23;
                    uint singleSig      = (halfSign & 0x03ffu) << 13;
                    decoded = singleSign + singleExponent + singleSig;
                }
                break;

            case 0x7c00u:     /* inf or NaN */
                /* All-ones exponent and a copy of the significand */
                decoded = singleSign + 0x7f800000u + ((encoded & 0x03ffu) << 13);
                break;

            default:     /* normalized */
                /* Just need to adjust the exponent and shift */
                decoded = singleSign + (((encoded & 0x7fffu) + 0x1c000u) << 13);
                break;
            }

            return(UnsafeUtilities.ReinterpretCast <uint, float>(decoded));
        }
Exemplo n.º 2
0
        // https://blog.fpmurphy.com/2008/12/half-precision-floating-point-format_14.html
        private static ushort FloatToHalf(float value)
        {
            int i = UnsafeUtilities.ReinterpretCast <float, int>(value);
            int s = (i >> 16) & 0x00008000;                         // sign
            int e = ((i >> 23) & 0x000000ff) - (127 - 15);          // exponent
            int f = i & 0x007fffff;                                 // fraction

            // need to handle NaNs and Inf?
            if (e <= 0)
            {
                if (e < -10)
                {
                    if (s > 0)   // handle -0.0
                    {
                        return(0x8000);
                    }
                    else
                    {
                        return(0);
                    }
                }
                f = (f | 0x00800000) >> (1 - e);
                return(( ushort )(s | (f >> 13)));
            }
            else if (e == 0xff - (127 - 15))
            {
                if (f == 0)   // Inf
                {
                    return(( ushort )(s | 0x7c00));
                }
                else
                {
                    // NAN
                    f >>= 13;
                    return(( ushort )(s | 0x7c00 | f | (f == 0 ? 1 : 0)));
                }
            }
            else
            {
                if (e > 30)   // Overflow
                {
                    return(( ushort )(s | 0x7c00));
                }
                return(( ushort )(s | (e << 10) | (f >> 13)));
            }
        }