// ===================================================================================================================== // fennec, a free and open source game engine // Copyright © 2025 - 2026 Medusa Slockbower // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . // ===================================================================================================================== #ifndef FENNEC_METAPROGRAMMING_FLOAT_H #define FENNEC_METAPROGRAMMING_FLOAT_H #include #include inline void float_h() { std::ofstream out("fennec/lang/float.h"); out << "// =====================================================================================================================" << '\n'; out << "// fennec, a free and open source game engine" << '\n'; out << "// Copyright © 2025 - 2026 Medusa Slockbower" << '\n'; out << "//" << '\n'; out << "// This program is free software: you can redistribute it and/or modify" << '\n'; out << "// it under the terms of the GNU General Public License as published by" << '\n'; out << "// the Free Software Foundation, either version 3 of the License, or" << '\n'; out << "// (at your option) any later version." << '\n'; out << "//" << '\n'; out << "// This program is distributed in the hope that it will be useful," << '\n'; out << "// but WITHOUT ANY WARRANTY; without even the implied warranty of" << '\n'; out << "// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the" << '\n'; out << "// GNU General Public License for more details." << '\n'; out << "//" << '\n'; out << "// You should have received a copy of the GNU General Public License" << '\n'; out << "// along with this program. If not, see ." << '\n'; out << "// =====================================================================================================================" << '\n'; out << "" << '\n'; out << "///" << '\n'; out << "/// \\file fennec/lang/float.h" << '\n'; out << "/// \\brief metaprogramming floating point type info" << '\n'; out << "///" << '\n'; out << "///" << '\n'; out << "/// \\details This file is automatically generated for the current build environment." << '\n'; out << "///" << '\n'; out << "/// Environment for this build: " FENNEC_LONG_COMPILER_NAME << '\n'; out << "///" << '\n'; out << "/// \\copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))" << '\n'; out << "///" << '\n'; out << "///" << '\n'; out << "" << '\n'; out << "#ifndef FENNEC_LANG_FLOAT_H" << '\n'; out << "#define FENNEC_LANG_FLOAT_H" << '\n'; out << "" << '\n'; out << "#include " << '\n'; out << "" << '\n'; // MAYBE TODO: Generate info without C++ STDLIB to compile natively on platforms without support out << "#undef FLT_HAS_INFINITY" << '\n'; out << "#undef FLT_HAS_QUIET_NAN" << '\n'; out << "#undef FLT_HAS_SIGNALING_NAN" << '\n'; out << "#undef FLT_HAS_DENORM" << '\n'; out << "#undef FLT_HAS_DENORM_LOSS" << '\n'; out << "#undef FLT_ROUNDS" << '\n'; out << "#undef FLT_IS_IEC559" << '\n'; out << "#undef FLT_MANT_DIG" << '\n'; out << "#undef FLT_DIG" << '\n'; out << "#undef FLT_DECIMAL_DIG" << '\n'; out << "#undef FLT_RADIX" << '\n'; out << "#undef FLT_MIN_EXP" << '\n'; out << "#undef FLT_MAX_EXP" << '\n'; out << "#undef FLT_MIN_10_EXP" << '\n'; out << "#undef FLT_MAX_10_EXP" << '\n'; out << "#undef FLT_TRAPS" << '\n'; out << "#undef FLT_TINYNESS_BEFORE" << '\n'; out << "#undef FLT_MIN" << '\n'; out << "#undef FLT_MAX" << '\n'; out << "#undef FLT_EPSILON" << '\n'; out << "#undef FLT_INF" << '\n'; out << "#undef FLT_QUIET_NAN" << '\n'; out << "#undef FLT_SIGNALING_NAN" << '\n'; out << "#undef FLT_DENORM_MIN" << '\n'; out << "#undef FLT_ROUND_ERR" << '\n'; out << "" << '\n'; out << R"(/// \brief Does \f$float\f$ have an infinity?)" << '\n'; out << "#define FLT_HAS_INFINITY " << std::dec << std::numeric_limits::has_infinity << '\n'; out << R"(/// \brief Does \f$float\f$ have a quiet NaN?)" << '\n'; out << "#define FLT_HAS_QUIET_NAN " << std::dec << std::numeric_limits::has_quiet_NaN << '\n'; out << R"(/// \brief Does \f$float\f$ have a signaling NaN?)" << '\n'; out << "#define FLT_HAS_SIGNALING_NAN " << std::dec << std::numeric_limits::has_signaling_NaN << '\n'; out << R"(/// \brief Does \f$float\f$ use denormalization?)" << '\n'; out << "#define FLT_HAS_DENORM " << std::dec << std::numeric_limits::has_denorm << '\n'; out << R"(/// \brief Does \f$float\f$ have loss with denormalization?)" << '\n'; out << "#define FLT_HAS_DENORM_LOSS " << std::dec << std::numeric_limits::has_denorm_loss << '\n'; out << R"(/// \brief What rounding style does \f$float\f$ use?)" << '\n'; out << "#define FLT_ROUNDS " << std::dec << std::numeric_limits::round_style << '\n'; out << R"(/// \brief Does \f$float\f$ use the IEEE floating point specification?)" << '\n'; out << "#define FLT_IS_IEC559 " << std::dec << std::numeric_limits::is_iec559 << '\n'; out << R"(/// \brief The number of mantissa bits in \f$float\f$.)" << '\n'; out << "#define FLT_MANT_DIG " << std::dec << std::numeric_limits::digits << '\n'; out << R"(/// \brief The number of decimal digits guaranteed to be preserved in a \f$float\f$ → \f$text\f$ → \f$float\f$.)" << '\n'; out << "#define FLT_DIG " << std::dec << std::numeric_limits::digits10 << '\n'; out << R"(/// \brief The decimal precision required to serialize and deserialize a \f$float\f$.)" << '\n'; out << "#define FLT_DECIMAL_DIG " << std::dec << std::numeric_limits::max_digits10 << '\n'; out << R"(/// \brief The radix, or integer base, used to represent a \f$float\f$.)" << '\n'; out << "#define FLT_RADIX " << std::dec << std::numeric_limits::radix << '\n'; out << R"(/// \brief The minimum negative integer such that \f${FLT_RADIX}^{FLT_MIN_EXP}\f$ results in a normalized \f$float\f$.)" << '\n'; out << "#define FLT_MIN_EXP " << std::dec << std::numeric_limits::min_exponent << '\n'; out << R"(/// \brief The maximum positive integer such that \f${FLT_RADIX}^{FLT_MAX_EXP}\f$ results in a non-infinite \f$float\f$.)" << '\n'; out << "#define FLT_MAX_EXP " << std::dec << std::numeric_limits::max_exponent << '\n'; out << R"(/// \brief The minimum negative integer such that \f${10}^{FLT_MIN_EXP}\f$ results in a normalized \f$float\f$.)" << '\n'; out << "#define FLT_MIN_10_EXP " << std::dec << std::numeric_limits::min_exponent10 << '\n'; out << R"(/// \brief The maximum positive integer such that \f${10}^{FLT_MAX_EXP}\f$ results in a non-infinite \f$float\f$.)" << '\n'; out << "#define FLT_MAX_10_EXP " << std::dec << std::numeric_limits::max_exponent10 << '\n'; out << R"(/// \brief Do arithmetics operations with \f$float\f$ trap?)" << '\n'; out << "#define FLT_TRAPS " << std::dec << std::numeric_limits::traps << '\n'; out << R"(/// \brief Do arithmetics operations with \f$float\f$ check for underflow?)" << '\n'; out << "#define FLT_TINYNESS_BEFORE " << std::dec << std::numeric_limits::tinyness_before << '\n'; out << R"(/// \brief Smallest positive, finite, normal value of \f$float\f$.)" << '\n'; out << "#define FLT_MIN " << "fennec::bit_cast(0x" << std::hex << std::bit_cast(std::numeric_limits::min() ) << ")" << '\n'; out << R"(/// \brief Largest positive, finite value of \f$float\f$.)" << '\n'; out << "#define FLT_MAX " << "fennec::bit_cast(0x" << std::hex << std::bit_cast(std::numeric_limits::max() ) << ")" << '\n'; out << R"(/// \brief The difference between \f$1.0\f$ and the next representable value of \f$float\f$.)" << '\n'; out << "#define FLT_EPSILON " << "fennec::bit_cast(0x" << std::hex << std::bit_cast(std::numeric_limits::epsilon() ) << ")" << '\n'; out << R"(/// \brief A value representing \f$\inf\f$ of type \f$float\f$.)" << '\n'; out << "#define FLT_INF " << "fennec::bit_cast(0x" << std::hex << std::bit_cast(std::numeric_limits::infinity() ) << ")" << '\n'; out << R"(/// \brief A value representing \f$NaN\f$ of type \f$float\f$ that does not trap.)" << '\n'; out << "#define FLT_QUIET_NAN " << "fennec::bit_cast(0x" << std::hex << std::bit_cast(std::numeric_limits::quiet_NaN() ) << ")" << '\n'; out << R"(/// \brief A value representing \f$NaN\f$ of type \f$float\f$ that traps.)" << '\n'; out << "#define FLT_SIGNALING_NAN " << "fennec::bit_cast(0x" << std::hex << std::bit_cast(std::numeric_limits::signaling_NaN()) << ")" << '\n'; out << R"(/// \brief Smallest positive, finite, subnormal value of \f$float\f$.)" << '\n'; out << "#define FLT_DENORM_MIN " << "fennec::bit_cast(0x" << std::hex << std::bit_cast(std::numeric_limits::denorm_min() ) << ")" << '\n'; out << R"(/// \brief Maximum rounding error of type \f$float\f$.)" << '\n'; out << "#define FLT_ROUND_ERR " << "fennec::bit_cast(0x" << std::hex << std::bit_cast(std::numeric_limits::round_error() ) << ")" << '\n'; out << "" << '\n'; out << "#undef DBL_HAS_INFINITY" << '\n'; out << "#undef DBL_HAS_QUIET_NAN" << '\n'; out << "#undef DBL_HAS_SIGNALING_NAN" << '\n'; out << "#undef DBL_HAS_DENORM" << '\n'; out << "#undef DBL_HAS_DENORM_LOSS" << '\n'; out << "#undef DBL_ROUNDS" << '\n'; out << "#undef DBL_IS_IEC559" << '\n'; out << "#undef DBL_MANT_DIG" << '\n'; out << "#undef DBL_DIG" << '\n'; out << "#undef DBL_DECIMAL_DIG" << '\n'; out << "#undef DBL_RADIX" << '\n'; out << "#undef DBL_MIN_EXP" << '\n'; out << "#undef DBL_MAX_EXP" << '\n'; out << "#undef DBL_MIN_10_EXP" << '\n'; out << "#undef DBL_MAX_10_EXP" << '\n'; out << "#undef DBL_TRAPS" << '\n'; out << "#undef DBL_TINYNESS_BEFORE" << '\n'; out << "#undef DBL_MIN" << '\n'; out << "#undef DBL_MAX" << '\n'; out << "#undef DBL_EPSILON" << '\n'; out << "#undef DBL_INF" << '\n'; out << "#undef DBL_QUIET_NAN" << '\n'; out << "#undef DBL_SIGNALING_NAN" << '\n'; out << "#undef DBL_DENORM_MIN" << '\n'; out << "#undef DBL_ROUND_ERR" << '\n'; out << "" << '\n'; out << R"(/// \brief Does \f$double\f$ have an infinity?)" << '\n'; out << "#define DBL_HAS_INFINITY " << std::dec << std::numeric_limits::has_infinity << '\n'; out << R"(/// \brief Does \f$double\f$ have a quiet NaN?)" << '\n'; out << "#define DBL_HAS_QUIET_NAN " << std::dec << std::numeric_limits::has_quiet_NaN << '\n'; out << R"(/// \brief Does \f$double\f$ have a signaling NaN?)" << '\n'; out << "#define DBL_HAS_SIGNALING_NAN " << std::dec << std::numeric_limits::has_signaling_NaN << '\n'; out << R"(/// \brief Does \f$double\f$ use denormalization?)" << '\n'; out << "#define DBL_HAS_DENORM " << std::dec << std::numeric_limits::has_denorm << '\n'; out << R"(/// \brief Does \f$double\f$ have loss with denormalization?)" << '\n'; out << "#define DBL_HAS_DENORM_LOSS " << std::dec << std::numeric_limits::has_denorm_loss << '\n'; out << R"(/// \brief What rounding style does \f$double\f$ use?)" << '\n'; out << "#define DBL_ROUNDS " << std::dec << std::numeric_limits::round_style << '\n'; out << R"(/// \brief Does \f$double\f$ use the IEEE doubleing point specification?)" << '\n'; out << "#define DBL_IS_IEC559 " << std::dec << std::numeric_limits::is_iec559 << '\n'; out << R"(/// \brief The number of mantissa bits in \f$double\f$.)" << '\n'; out << "#define DBL_MANT_DIG " << std::dec << std::numeric_limits::digits << '\n'; out << R"(/// \brief The number of decimal digits guaranteed to be preserved in a \f$double\f$ → \f$text\f$ → \f$double\f$.)" << '\n'; out << "#define DBL_DIG " << std::dec << std::numeric_limits::digits10 << '\n'; out << R"(/// \brief The decimal precision required to serialize and deserialize a \f$double\f$.)" << '\n'; out << "#define DBL_DECIMAL_DIG " << std::dec << std::numeric_limits::max_digits10 << '\n'; out << R"(/// \brief The radix, or integer base, used to represent a \f$double\f$.)" << '\n'; out << "#define DBL_RADIX " << std::dec << std::numeric_limits::radix << '\n'; out << R"(/// \brief The minimum negative integer such that \f${DBL_RADIX}^{DBL_MIN_EXP}\f$ results in a normalized \f$double\f$.)" << '\n'; out << "#define DBL_MIN_EXP " << std::dec << std::numeric_limits::min_exponent << '\n'; out << R"(/// \brief The maximum positive integer such that \f${DBL_RADIX}^{DBL_MAX_EXP}\f$ results in a non-infinite \f$double\f$.)" << '\n'; out << "#define DBL_MAX_EXP " << std::dec << std::numeric_limits::max_exponent << '\n'; out << R"(/// \brief The minimum negative integer such that \f${10}^{DBL_MIN_EXP}\f$ results in a normalized \f$double\f$.)" << '\n'; out << "#define DBL_MIN_10_EXP " << std::dec << std::numeric_limits::min_exponent10 << '\n'; out << R"(/// \brief The maximum positive integer such that \f${10}^{DBL_MAX_EXP}\f$ results in a non-infinite \f$double\f$.)" << '\n'; out << "#define DBL_MAX_10_EXP " << std::dec << std::numeric_limits::max_exponent10 << '\n'; out << R"(/// \brief Do arithmetics operations with \f$double\f$ trap?)" << '\n'; out << "#define DBL_TRAPS " << std::dec << std::numeric_limits::traps << '\n'; out << R"(/// \brief Do arithmetics operations with \f$double\f$ check for underflow?)" << '\n'; out << "#define DBL_TINYNESS_BEFORE " << std::dec << std::numeric_limits::tinyness_before << '\n'; out << R"(/// \brief Smallest positive, finite, normal value of \f$double\f$.)" << '\n'; out << "#define DBL_MIN " << "fennec::bit_cast(0x" << std::hex << std::bit_cast(std::numeric_limits::min() ) << "ll)" << '\n'; out << R"(/// \brief Largest positive, finite value of \f$double\f$.)" << '\n'; out << "#define DBL_MAX " << "fennec::bit_cast(0x" << std::hex << std::bit_cast(std::numeric_limits::max() ) << "ll)" << '\n'; out << R"(/// \brief The difference between \f$1.0\f$ and the next representable value of \f$double\f$.)" << '\n'; out << "#define DBL_EPSILON " << "fennec::bit_cast(0x" << std::hex << std::bit_cast(std::numeric_limits::epsilon() ) << "ll)" << '\n'; out << R"(/// \brief A value representing \f$\inf\f$ of type \f$double\f$.)" << '\n'; out << "#define DBL_INF " << "fennec::bit_cast(0x" << std::hex << std::bit_cast(std::numeric_limits::infinity() ) << "ll)" << '\n'; out << R"(/// \brief A value representing \f$NaN\f$ of type \f$double\f$ that does not trap.)" << '\n'; out << "#define DBL_QUIET_NAN " << "fennec::bit_cast(0x" << std::hex << std::bit_cast(std::numeric_limits::quiet_NaN() ) << "ll)" << '\n'; out << R"(/// \brief A value representing \f$NaN\f$ of type \f$double\f$ that traps.)" << '\n'; out << "#define DBL_SIGNALING_NAN " << "fennec::bit_cast(0x" << std::hex << std::bit_cast(std::numeric_limits::signaling_NaN()) << "ll)" << '\n'; out << R"(/// \brief Smallest positive, finite, subnormal value of \f$double\f$.)" << '\n'; out << "#define DBL_DENORM_MIN " << "fennec::bit_cast(0x" << std::hex << std::bit_cast(std::numeric_limits::denorm_min() ) << "ll)" << '\n'; out << R"(/// \brief Maximum rounding error of type \f$double\f$.)" << '\n'; out << "#define DBL_ROUND_ERR " << "fennec::bit_cast(0x" << std::hex << std::bit_cast(std::numeric_limits::round_error() ) << "ll)" << '\n'; out << "" << '\n'; out << "#endif // FENNEC_LANG_FLOAT_H" << '\n'; out.close(); return; } #endif //FLOAT_H