#ifndef TFLOAT16_H
#define TFLOAT16_H

// crude implementation of float16 for platforms that do not support _Float16

#include <stdint.h>

class TFloat16
{
    uint16_t b16;
public:
    TFloat16(){ b16 = 0; }
    explicit inline TFloat16(float f)
    {
        uint32_t i = *reinterpret_cast<uint32_t*>(&f);
        uint32_t sign = (i >> 16) & 0x8000;
        uint32_t exp = (i >> 23) & 0xff;
        uint32_t mantisa = (i & 0x7fffff) >> 13;

        b16 = 0;
        if(exp < 111)
        {
            // do nothing it map to 0
        }
        else if(exp == 111)
        {
            b16 |= sign;
            b16 |= mantisa;
        }
        else if(exp == 255)//inf or nan
        {
            b16 = 0x7c00;
            b16 |= sign;
            b16 |= mantisa;
        }
        else if(exp > 142)
        {
            b16 = 0x7c00;// inf
            b16 |= sign;
        }
        else
        {
            b16 |= sign;
            b16 |= (exp - 112) << 10;
            b16 |= mantisa;
        }
    }
    friend TFloat16 operator*(TFloat16 a, TFloat16 b)
    {
        return TFloat16(static_cast<float>(a) * static_cast<float>(b));
    }
    operator float() const
    {
        uint32_t i = 0;
        uint32_t sign = b16 & 0x8000;
        uint32_t exp = (b16 & 0x7c00) >> 10;
        if(b16)
        {
            i |= sign << 16;
            if(exp==31)i |= 0x7f800000;
            else i |= (exp + 112) << 23;
            i |= (b16 & 0x3ff) << 13;
        }
        return *reinterpret_cast<float*>(&i);
    }
};

#endif // TFLOAT16_H
