#ifndef HALIDE_FLOAT16_H #define HALIDE_FLOAT16_H #include "runtime/HalideRuntime.h" #include <stdint.h> #include <string> #include "RoundingMode.h" #include "Util.h" namespace Halide { /** Class that provides a type that implements half precision * floating point (IEEE754 2008 binary16) in software. * * This type is enforced to be 16-bits wide and maintains no state * other than the raw IEEE754 binary16 bits so that it can passed * to code that checks a type's size and used for buffer_t allocation. * */ struct float16_t { // NOTE: Do not use virtual methods here // it will change the size of this data type. /// \name Constructors /// @{ /** Construct from a float using a particular rounding mode. * A warning will be emitted if the result cannot be represented exactly * and error will be raised if the conversion results in overflow. * * \param value the input float * \param roundingMode The rounding mode to use * */ EXPORT explicit float16_t(float value, RoundingMode roundingMode=RoundingMode::ToNearestTiesToEven); /** Construct from a double using a particular rounding mode. * A warning will be emitted if the result cannot be represented exactly * and error will be raised if the conversion results in overflow. * * \param value the input double * \param roundingMode The rounding mode to use * */ EXPORT explicit float16_t(double value, RoundingMode roundingMode=RoundingMode::ToNearestTiesToEven); /** Construct by parsing a string using a particular rounding mode. * A warning will be emitted if the result cannot be represented exactly * and error will be raised if the conversion results in overflow. * * \param stringRepr the input string. The string maybe in C99 hex format * (e.g. ``-0x1.000p-1``) or in a decimal (e.g.``-0.5``) format. * * \param roundingMode The rounding mode to use * */ EXPORT explicit float16_t(const char *stringRepr, RoundingMode roundingMode=RoundingMode::ToNearestTiesToEven); /** Construct a float16_t with the bits initialised to 0. This represents * positive zero.*/ EXPORT float16_t(); /// @} // Use explicit to avoid accidently raising the precision /** Cast to float */ EXPORT explicit operator float() const; /** Cast to double */ EXPORT explicit operator double() const; // Be explicit about how the copy constructor is expected to behave EXPORT float16_t(const float16_t&) = default; // Be explicit about how assignment is expected to behave EXPORT float16_t& operator=(const float16_t&) = default; /** \name Convenience "constructors" */ /**@{*/ /** Get a new float16_t that represents zero * \param positive if true then returns positive zero otherwise returns * negative zero. */ EXPORT static float16_t make_zero(bool positive); /** Get a new float16_t that represents infinity * \param positive if true then returns positive infinity otherwise returns * negative infinity. */ EXPORT static float16_t make_infinity(bool positive); /** Get a new float16_t that represents NaN (not a number) */ EXPORT static float16_t make_nan(); /** Get a new float16_t with the given raw bits * * \param bits The bits conformant to IEEE754 binary16 */ EXPORT static float16_t make_from_bits(uint16_t bits); /** Get a new float16_t from a signed integer. * It is not provided as a constructor to avoid call ambiguity * */ EXPORT static float16_t make_from_signed_int(int64_t value, RoundingMode roundingMode=RoundingMode::ToNearestTiesToEven); /**@}*/ /**\name Arithmetic operators * These compute the result of an arithmetic operation * using a particular ``roundingMode`` and return a new float16_t * representing the result. * * Exceptions are ignored. */ /**@{*/ /** add */ EXPORT float16_t add(float16_t rhs, RoundingMode roundingMode) const; /** subtract */ EXPORT float16_t subtract(float16_t rhs, RoundingMode roundingMode) const; /** multiply */ EXPORT float16_t multiply(float16_t rhs, RoundingMode roundingMode) const; /** divide */ EXPORT float16_t divide(float16_t denominator, RoundingMode roundingMode) const; /** IEEE-754 2008 5.3.1 General operations - remainder **/ EXPORT float16_t remainder(float16_t denominator) const; /** C fmod() */ EXPORT float16_t mod(float16_t denominator, RoundingMode roudingMode) const; /**@}*/ /** Return a new float16_t with a negated sign bit*/ EXPORT float16_t operator-() const; /** \name Overloaded arithmetic operators for convenience * These operators assume RoundingMode::ToNearestTiesToEven rounding */ /**@{*/ EXPORT float16_t operator+(float16_t rhs) const; EXPORT float16_t operator-(float16_t rhs) const; EXPORT float16_t operator*(float16_t rhs) const; EXPORT float16_t operator/(float16_t rhs) const; /**@}*/ /** \name Comparison operators */ /**@{*/ /** Equality */ EXPORT bool operator==(float16_t rhs) const; /** Not equal */ EXPORT bool operator!=(float16_t rhs) const { return !(*this == rhs); } /** Greater than */ EXPORT bool operator>(float16_t rhs) const; /** Less than */ EXPORT bool operator<(float16_t rhs) const; /** Greater than or equal to*/ EXPORT bool operator>=(float16_t rhs) const { return (*this > rhs) || (*this == rhs); } /** Less than or equal to*/ EXPORT bool operator<=(float16_t rhs) const { return (*this < rhs) || (*this == rhs); } /** \return true if and only if the float16_t and ``rhs`` are not ordered. E.g. * NaN and a normalised number */ EXPORT bool are_unordered(float16_t rhs) const; /**@}*/ /** \name String output methods */ /**@{*/ /** Return a string in the C99 hex format (e.g.\ ``-0x1.000p-1``) that * represents this float16_t precisely. */ EXPORT std::string to_hex_string() const; /** Returns a string in a decimal scientific notation (e.g.\ ``-5.0E-1``) * that represents the closest decimal value to this float16_t precise to * the number of significant digits requested. * * \param significantDigits The number of significant digits to use. If * set to ``0`` then string returned will have enough precision to * construct the same float16_t when using * RoundingMode::ToNearestTiesToEven */ EXPORT std::string to_decimal_string(unsigned int significantDigits = 0) const; /**@}*/ /** \name Properties */ /*@{*/ EXPORT bool is_nan() const; EXPORT bool is_infinity() const; EXPORT bool is_negative() const; EXPORT bool is_zero() const; /*@}*/ /** Returns the bits that represent this float16_t. * * An alternative method to access the bits is to cast a pointer * to this instance as a pointer to a uint16_t. **/ EXPORT uint16_t to_bits() const; private: // The raw bits. // This must be the **ONLY** data member so that // this data type is 16-bits wide. uint16_t data; }; } // namespace Halide template<> HALIDE_ALWAYS_INLINE halide_type_t halide_type_of<Halide::float16_t>() { return halide_type_t(halide_type_float, 16); } #endif