From ed7a5c72e29fbaa6d5641ca21b2e401e7f42c057 Mon Sep 17 00:00:00 2001 From: BobSmun <6492115+BobSmun@users.noreply.github.com> Date: Sun, 22 Sep 2024 15:17:10 +0800 Subject: [PATCH 1/4] add templates for ieee754 2019 types --- includes/type/ieee754_binary.pat | 114 +++++++++++++ includes/type/ieee754_decimal.pat | 258 ++++++++++++++++++++++++++++++ 2 files changed, 372 insertions(+) create mode 100644 includes/type/ieee754_binary.pat create mode 100644 includes/type/ieee754_decimal.pat diff --git a/includes/type/ieee754_binary.pat b/includes/type/ieee754_binary.pat new file mode 100644 index 00000000..1300fd79 --- /dev/null +++ b/includes/type/ieee754_binary.pat @@ -0,0 +1,114 @@ +#pragma once + +import std.core; +import std.math; +import std.io; +import std.sys; + +/** + Types representing IEEE 754 2019 compatible binary floating point numbers + defines: + IEEE754_SUPPRESS_USAGE_WARNING - suppresses warnings related to recommendation to use built-in types + IEEE754_UNSEAL - show internal bitfields +*/ +namespace auto ieee754 +{ + /** + Type representing a binary floating point number, taking a custom bias + @tparam exponent_width number of bits to use for the biased exponent + @tparam significand_width number of bits to use for the trailing significand field + @tparam bias exponent bias + */ + bitfield binary_with_bias + { + sign: 1; + biased_exponent: exponent_width; + significand: significand_width; + + //usage assertions, intentionally not suppressible + std::assert(exponent_width > 0, std::format("Invalid exponent_width! Expected >0, got {}", exponent_width)); + std::assert(significand_width > 0, std::format("Invalid significand_width! Expected >0, got {}", significand_width)); + +#ifndef IEEE754_SUPPRESS_USAGE_WARNING + //usage warnings, suppressible + if((exponent_width == 8) && (significand_width == 23)){ std::warning("IEEE 754 binary32 used, prefer the use of in-built type instead"); } + else if((exponent_width == 11) && (significand_width == 52)){ std::warning("IEEE 754 binary64 used, prefer the use of in-built type instead"); } + //else if((exponent_width == 15) && (significand_width == 112)){ std::warning("IEEE 754 binary128 used, prefer the use of in-built type instead"); } +#endif + } + [[ +#ifndef IEEE754_UNSEAL + sealed, +#endif + bitfield_order(std::core::BitfieldOrder::MostToLeastSignificant, 1 + exponent_width + significand_width), + format_read("ieee754::impl::format_binary"), + transform("ieee754::impl::transform_binary") + ]]; + + /** + Type representing a binary floating point number, using the canonical determination of bias + @tparam exponent_width number of bits to use for the biased exponent + @tparam significand_width number of bits to use for the trailing significand field + */ + using binary = binary_with_bias; + + namespace impl + { + fn format_binary(ref auto r) + { + //TODO: number of significant digits? + return std::format("{}", r); + }; + + fn transform_binary(ref auto r) + { + s8 sign = r.sign ? -1 : 1; + + //is the exponent all 1's + if(r.biased_exponent == ((1 << r.exponent_width) - 1)) + { + if(r.significand != 0) + { + //NaN's + //Note: payload not processed / decoded + return ((r.significand >> (r.significand_width - 1)) & 1) ? qNaN : sNaN; + } + else + { + //Inf's + return sign * Inf; + } + } + else if(r.biased_exponent == 0) + { + if(r.significand != 0) + { + //subnormal numbers + return sign + * std::math::pow(2.0, 1 - r.bias) + * (0.0 + (double(r.significand) / (1 << r.significand_width))); + } + else + { + //0's + return sign * 0; + } + } + //normal numbers + return sign + * std::math::pow(2, r.biased_exponent - r.bias) + * (1 + (double(r.significand) / (1 << r.significand_width))); + }; + } + + using binary16 = binary<5, 10>; //aka half + using binary32 = binary<8, 23>; //aka single or float - prefer the use of inbuilt-type instead + using binary64 = binary<11, 52>; //aka double - prefer the use of inbuilt-type instead + + //defined in IEEE 754 2019, but not currently supported + //using binary128 = binary<15, 112>; //aka quadruple - prefer the use of inbuilt-type instead, if available + //using binary160 = binary<16, 143>; + //using binary192 = binary<17, 174>; + //using binary224 = binary<18, 205>; + //using binary256 = binary<19, 236>; //aka octuple +} \ No newline at end of file diff --git a/includes/type/ieee754_decimal.pat b/includes/type/ieee754_decimal.pat new file mode 100644 index 00000000..c002e7d9 --- /dev/null +++ b/includes/type/ieee754_decimal.pat @@ -0,0 +1,258 @@ +#pragma once + +import std.core; +import std.math; +import std.io; +import std.sys; + +/** + Types representing IEEE 754 2019 compatible decimal floating point numbers + defines: + IEEE754_SUPPRESS_WARNING - suppresses warnings about canonicity of values being decoded + IEEE754_UNSEAL - show internal bitfields +*/ +namespace auto ieee754 +{ + /** + Decimal floating point numbers can be encoded using one of multiple methods + Selection of which method to use is implementation specific, and cannot be determined from the binary data alone + */ + enum decimal_encoding : u8 + { + binary = 2, // aka binary integer decimal (BID) + decimal = 10 // aka densely packed decimal (DPD) + }; + + /** + Type representing a decimal floating point number, taking a custom bias + @tparam combination_width number of bits to use for the biased exponent + @tparam significand_width number of bits to use for the trailing significand field + @tparam encoding whether to use binary or decimal encoding + @tparam bias exponent bias + */ + bitfield decimal_with_bias + { + sign: 1; + combination: combination_width; + significand: significand_width; + + //usage assertions, intentionally not suppressible + std::assert(combination_width > 5, std::format("Invalid combination_width! Expected >5, got {}", combination_width)); + std::assert(significand_width > 0, std::format("Invalid significand_width! Expected >0, got {}", significand_width)); + std::assert((encoding == decimal_encoding::binary) || (encoding == decimal_encoding::decimal), "Invalid encoding! Expected either decimal_encoding::binary or decimal_encoding::decimal"); + std::assert((significand_width % 10) == 0, std::format("Invalid significand_width! Expected multiple of 10, got {}", significand_width)); + + //PL currently only supports up to u128 + std::assert((encoding == decimal_encoding::decimal) || ((significand_width + 4) <= 128), std::format("Invalid significand_width for binary encoding! Expected <= 120, got {}", significand_width)); + } + [[ +#ifndef IEEE754_UNSEAL + sealed, +#endif + bitfield_order(std::core::BitfieldOrder::MostToLeastSignificant, 1 + combination_width + significand_width), + format_read("ieee754::impl::format_decimal") + ]]; + + /** + Type representing a decimal floating point number, using the canonical determination of bias + @tparam combination_width number of bits to use for the biased exponent + @tparam significand_width number of bits to use for the trailing significand field + @tparam encoding whether to use binary or decimal encoding + */ + using decimal = decimal_with_bias; + + namespace impl + { + fn format_decimal(ref auto r) + { + s8 sign = r.sign ? -1 : 1; + auto w = r.combination_width - 5; + + if((r.combination >> w) & 0b11111 == 0b11111) + { + //NaN's + bool is_signaling = ((r.combination >> (w - 1)) & 1 == 1); + //Note: payload not processed / decoded + //Note: NaN might not be canonical +#ifndef IEEE754_SUPPRESS_WARNING + //check if combination field is canonical (all remaining bits are 0) + auto remaining_combination_bits = (r.combination & ((1 << (w - 1)) - 1)); + std::assert_warn(remaining_combination_bits == 0, std::format("NaN - remaining combination field bits not canonical! Expected 0, got {}", remaining_combination_bits)); + //TODO: also check if encoding of the payload is canonical +#endif + return is_signaling ? "sNaN" : "qNaN"; + } + else if((r.combination >> w) & 0b11111 == 0b11110) + { + //Inf's + //Note: Inf might not be canonical +#ifndef IEEE754_SUPPRESS_WARNING + //check if combination field is canonical (all remaining bits are 0) + auto remaining_combination_bits = r.combination & ((1 << w) - 1); + std::assert_warn(remaining_combination_bits == 0, std::format("Inf - remaining combination field bits not canonical! Expected 0, got {}", remaining_combination_bits)); + std::assert_warn(r.significand == 0, std::format("Inf - significand not canonical! Expected 0, got {}", r.significand)); +#endif + return r.sign ? "-Inf" : "Inf"; + } + else if(r.encoding == decimal_encoding::binary) + { + str output = r.sign ? "-" : ""; + //0 0 e ... e t t t => 00e...e, 0ttt{significand} + //0 1 e ... e t t t => 01e...e, 0ttt{significand} + //1 0 e ... e t t t => 10e...e, 0ttt{significand} + //1 1 0 0 e ... e t => 00e...e, 100t{significand} + //1 1 0 1 e ... e t => 01e...e, 100t{significand} + //1 1 1 0 e ... e t => 10e...e, 100t{significand} + s128 biased_exponent; + u128 full_significand; + if((r.combination >> (r.combination_width - 2)) & 0b11 == 0b11) + { + biased_exponent = (r.combination >> 1) & ((1 << (r.combination_width - 3)) - 1); + full_significand = ((0b1000 | (r.combination & 0b1)) << r.significand_width) | r.significand; + } + else + { + biased_exponent = (r.combination >> 3) & ((1 << (r.combination_width - 3)) - 1); + full_significand = ((r.combination & 0b111) << r.significand_width) | r.significand; + } + + u128 max_value = std::math::pow(10, 3 * (significand_width / 10)) - 1; + if((full_significand == 0) || (full_significand > max_value)) + { + //0s +#ifndef IEEE754_SUPPRESS_WARNING + std::assert_warn(full_significand == 0, std::format("0 - significand not canonical! Expected < {}, got {}", max_value, full_significand)); +#endif + return r.sign ? "-0" : "0"; + } + + return std::format("{}{}E{}{}", sign, full_significand, (biased_exponent - r.bias) < 0 ? "" : "+", biased_exponent - r.bias); + } + else if(r.encoding == decimal_encoding::decimal) + { + str output = r.sign ? "-" : ""; + //0 0 t t t e ... e => 00e...e, 0ttt.significand + //0 1 t t t e ... e => 01e...e, 0ttt.significand + //1 0 t t t e ... e => 10e...e, 0ttt.significand + //1 1 0 0 t e ... e => 00e...e, 100t.significand + //1 1 0 1 t e ... e => 01e...e, 100t.significand + //1 1 1 0 t e ... e => 10e...e, 100t.significand + s128 biased_exponent = (r.combination & ((1 << w) - 1)); + if((r.combination >> (r.combination_width - 2)) & 0b11 == 0b11) + { + biased_exponent |= (((r.combination >> (r.combination_width - 4)) & 0b11) << w); + output = std::format("{}{}.", output, 8 | ((r.combination >> w) & 1)); + } + else if((((r.combination >> w) & 0b111) == 0) && (r.significand == 0)) + { + //0s + return r.sign ? "-0" : "0"; + } + else + { + biased_exponent |= (((r.combination >> (r.combination_width - 2)) & 0b11) << w); + output = std::format("{}{}.", output, (r.combination >> w) & 0b111); + } + + //every 10 bit of significand gets decoded using one of + //9 8 7 6 5 4 3 2 1 0 2 1 0 + //all small + //a b c d e f 0 g h i => 0abc 0def 0ghi + //1 large + //a b c d e f 1 0 0 i => 0abc 0def 100i + //a b c g h f 1 0 1 i => 0abc 100f 0ghi + //g h c d e f 1 1 0 i => 100c 0def 0ghi + //2 large + //g h c 0 0 f 1 1 1 i => 100c 100f 0ghi + //d e c 0 1 f 1 1 1 i => 100c 0def 100i + //a b c 1 0 f 1 1 1 i => 0abc 100f 100i + //all large + //x x c 1 1 f 1 1 1 i => 100c 100f 100i + for(s128 i = r.significand_width - 10, i >= 0, i -= 10) + { + auto b9 = (r.significand >> i+9) & 1; + auto b8 = (r.significand >> i+8) & 1; + auto b6 = (r.significand >> i+6) & 1; + auto b5 = (r.significand >> i+5) & 1; + auto b2 = (r.significand >> i+2) & 1; + auto b1 = (r.significand >> i+1) & 1; + + auto d0 = (r.significand >> i+0) & 1; + auto d1 = (r.significand >> i+4) & 1; + auto d2 = (r.significand >> i+7) & 1; + + if(((r.significand >> i+3) & 1) == 0) + { + d0 |= (b2 << 2) | (b1 << 1); + d1 |= (b6 << 2) | (b5 << 1); + d2 |= (b9 << 2) | (b8 << 1); + } + else //b3 == 1 + { + auto b21 = (r.significand >> i+1) & 0b11; + if(b21 == 0) + { + d0 |= 0b1000; + d1 |= (b6 << 2) | (b5 << 1); + d2 |= (b9 << 2) | (b8 << 1); + } + else if(b21 == 1) + { + d0 |= (b6 << 2) | (b5 << 1); + d1 |= 0b1000; + d2 |= (b9 << 2) | (b8 << 1); + } + else if(b21 == 2) + { + d0 |= (b9 << 2) | (b8 << 1); + d1 |= (b6 << 2) | (b5 << 1); + d2 |= 0b1000; + } + else //b21 == 0b11 + { + auto b56 = (r.significand >> i+5) & 0b11; + if(b56 == 0) + { + d0 |= (b9 << 2) | (b8 << 1); + d1 |= 0b1000; + d2 |= 0b1000; + } + else if(b56 == 1) + { + d0 |= 0b1000; + d1 |= (b9 << 2) | (b8 << 1); + d2 |= 0b1000; + } + else if(b56 == 2) + { + d0 |= 0b1000; + d1 |= 0b1000; + d2 |= (b9 << 2) | (b8 << 1); + } + else //b56 == 0b11 + { + d0 |= 0b1000; + d1 |= 0b1000; + d2 |= 0b1000; + } + } + } + output = std::format("{}{}{}{}", output, d2, d1, d0); + } + + return std::format("{}E{}{}", output, (biased_exponent - r.bias) < 0 ? "" : "+", biased_exponent - r.bias); + } + }; + } + + using decimal32 = decimal<11, 20, encoding>; + using decimal64 = decimal<13, 50, encoding>; + using decimal96 = decimal<15, 80, encoding>; + using decimal128 = decimal<17, 110, encoding>; + + //defined in IEEE 754 2019, but only decimal encoding currently supported + using decimal160 = decimal<19, 140, encoding>; + using decimal192 = decimal<21, 170, encoding>; + using decimal224 = decimal<23, 200, encoding>; + using decimal256 = decimal<25, 230, encoding>; +} \ No newline at end of file From 7ad1cb34681305fb234fba3cd9fd4c83c3a36719 Mon Sep 17 00:00:00 2001 From: BobSmun <6492115+BobSmun@users.noreply.github.com> Date: Sat, 30 Nov 2024 08:59:11 +0800 Subject: [PATCH 2/4] Move ieee754 types into 'type' namespace --- includes/type/ieee754_binary.pat | 8 +++++--- includes/type/ieee754_decimal.pat | 6 ++++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/includes/type/ieee754_binary.pat b/includes/type/ieee754_binary.pat index 1300fd79..071fed31 100644 --- a/includes/type/ieee754_binary.pat +++ b/includes/type/ieee754_binary.pat @@ -5,13 +5,14 @@ import std.math; import std.io; import std.sys; +namespace auto type { /** Types representing IEEE 754 2019 compatible binary floating point numbers defines: IEEE754_SUPPRESS_USAGE_WARNING - suppresses warnings related to recommendation to use built-in types IEEE754_UNSEAL - show internal bitfields */ -namespace auto ieee754 +namespace ieee754 { /** Type representing a binary floating point number, taking a custom bias @@ -41,8 +42,8 @@ namespace auto ieee754 sealed, #endif bitfield_order(std::core::BitfieldOrder::MostToLeastSignificant, 1 + exponent_width + significand_width), - format_read("ieee754::impl::format_binary"), - transform("ieee754::impl::transform_binary") + format_read("type::ieee754::impl::format_binary"), + transform("type::ieee754::impl::transform_binary") ]]; /** @@ -111,4 +112,5 @@ namespace auto ieee754 //using binary192 = binary<17, 174>; //using binary224 = binary<18, 205>; //using binary256 = binary<19, 236>; //aka octuple +} } \ No newline at end of file diff --git a/includes/type/ieee754_decimal.pat b/includes/type/ieee754_decimal.pat index c002e7d9..7bfd368b 100644 --- a/includes/type/ieee754_decimal.pat +++ b/includes/type/ieee754_decimal.pat @@ -5,13 +5,14 @@ import std.math; import std.io; import std.sys; +namespace auto type { /** Types representing IEEE 754 2019 compatible decimal floating point numbers defines: IEEE754_SUPPRESS_WARNING - suppresses warnings about canonicity of values being decoded IEEE754_UNSEAL - show internal bitfields */ -namespace auto ieee754 +namespace ieee754 { /** Decimal floating point numbers can be encoded using one of multiple methods @@ -50,7 +51,7 @@ namespace auto ieee754 sealed, #endif bitfield_order(std::core::BitfieldOrder::MostToLeastSignificant, 1 + combination_width + significand_width), - format_read("ieee754::impl::format_decimal") + format_read("type::ieee754::impl::format_decimal") ]]; /** @@ -255,4 +256,5 @@ namespace auto ieee754 using decimal192 = decimal<21, 170, encoding>; using decimal224 = decimal<23, 200, encoding>; using decimal256 = decimal<25, 230, encoding>; +} } \ No newline at end of file From dbb606eb82eb510fc2b69f876ea11057376a1ff2 Mon Sep 17 00:00:00 2001 From: BobSmun <6492115+BobSmun@users.noreply.github.com> Date: Sun, 1 Dec 2024 11:48:58 +0800 Subject: [PATCH 3/4] * Use 'in' settings instead of #defines, to allow modifying behaviour * Remove unseal, and make default not sealed * Merge namespace --- includes/type/ieee754_binary.pat | 33 +++++++++---------- includes/type/ieee754_decimal.pat | 53 +++++++++++++++---------------- 2 files changed, 41 insertions(+), 45 deletions(-) diff --git a/includes/type/ieee754_binary.pat b/includes/type/ieee754_binary.pat index 071fed31..af990ddc 100644 --- a/includes/type/ieee754_binary.pat +++ b/includes/type/ieee754_binary.pat @@ -5,15 +5,15 @@ import std.math; import std.io; import std.sys; -namespace auto type { -/** - Types representing IEEE 754 2019 compatible binary floating point numbers - defines: - IEEE754_SUPPRESS_USAGE_WARNING - suppresses warnings related to recommendation to use built-in types - IEEE754_UNSEAL - show internal bitfields -*/ -namespace ieee754 +// Types representing IEEE 754 2019 compatible binary floating point numbers +namespace auto type::ieee754 { + /** + settings: + IEEE754_SUPPRESS_USAGE_WARNING - suppresses warnings related to recommendation to use built-in types + */ + bool IEEE754_SUPPRESS_USAGE_WARNING in; + /** Type representing a binary floating point number, taking a custom bias @tparam exponent_width number of bits to use for the biased exponent @@ -30,17 +30,15 @@ namespace ieee754 std::assert(exponent_width > 0, std::format("Invalid exponent_width! Expected >0, got {}", exponent_width)); std::assert(significand_width > 0, std::format("Invalid significand_width! Expected >0, got {}", significand_width)); -#ifndef IEEE754_SUPPRESS_USAGE_WARNING - //usage warnings, suppressible - if((exponent_width == 8) && (significand_width == 23)){ std::warning("IEEE 754 binary32 used, prefer the use of in-built type instead"); } - else if((exponent_width == 11) && (significand_width == 52)){ std::warning("IEEE 754 binary64 used, prefer the use of in-built type instead"); } - //else if((exponent_width == 15) && (significand_width == 112)){ std::warning("IEEE 754 binary128 used, prefer the use of in-built type instead"); } -#endif + if(!IEEE754_SUPPRESS_USAGE_WARNING) + { + //usage warnings, suppressible + if((exponent_width == 8) && (significand_width == 23)){ std::warning("IEEE 754 binary32 used, prefer the use of in-built type instead"); } + else if((exponent_width == 11) && (significand_width == 52)){ std::warning("IEEE 754 binary64 used, prefer the use of in-built type instead"); } + //else if((exponent_width == 15) && (significand_width == 112)){ std::warning("IEEE 754 binary128 used, prefer the use of in-built type instead"); } + } } [[ -#ifndef IEEE754_UNSEAL - sealed, -#endif bitfield_order(std::core::BitfieldOrder::MostToLeastSignificant, 1 + exponent_width + significand_width), format_read("type::ieee754::impl::format_binary"), transform("type::ieee754::impl::transform_binary") @@ -112,5 +110,4 @@ namespace ieee754 //using binary192 = binary<17, 174>; //using binary224 = binary<18, 205>; //using binary256 = binary<19, 236>; //aka octuple -} } \ No newline at end of file diff --git a/includes/type/ieee754_decimal.pat b/includes/type/ieee754_decimal.pat index 7bfd368b..d00b6fa2 100644 --- a/includes/type/ieee754_decimal.pat +++ b/includes/type/ieee754_decimal.pat @@ -5,15 +5,15 @@ import std.math; import std.io; import std.sys; -namespace auto type { -/** - Types representing IEEE 754 2019 compatible decimal floating point numbers - defines: - IEEE754_SUPPRESS_WARNING - suppresses warnings about canonicity of values being decoded - IEEE754_UNSEAL - show internal bitfields -*/ -namespace ieee754 +// Types representing IEEE 754 2019 compatible decimal floating point numbers +namespace auto type::ieee754 { + /** + settings: + IEEE754_SUPPRESS_WARNING - suppresses warnings about canonicity of values being decoded + */ + bool IEEE754_SUPPRESS_WARNING in; + /** Decimal floating point numbers can be encoded using one of multiple methods Selection of which method to use is implementation specific, and cannot be determined from the binary data alone @@ -47,9 +47,6 @@ namespace ieee754 std::assert((encoding == decimal_encoding::decimal) || ((significand_width + 4) <= 128), std::format("Invalid significand_width for binary encoding! Expected <= 120, got {}", significand_width)); } [[ -#ifndef IEEE754_UNSEAL - sealed, -#endif bitfield_order(std::core::BitfieldOrder::MostToLeastSignificant, 1 + combination_width + significand_width), format_read("type::ieee754::impl::format_decimal") ]]; @@ -75,24 +72,26 @@ namespace ieee754 bool is_signaling = ((r.combination >> (w - 1)) & 1 == 1); //Note: payload not processed / decoded //Note: NaN might not be canonical -#ifndef IEEE754_SUPPRESS_WARNING - //check if combination field is canonical (all remaining bits are 0) - auto remaining_combination_bits = (r.combination & ((1 << (w - 1)) - 1)); - std::assert_warn(remaining_combination_bits == 0, std::format("NaN - remaining combination field bits not canonical! Expected 0, got {}", remaining_combination_bits)); - //TODO: also check if encoding of the payload is canonical -#endif + if(!IEEE754_SUPPRESS_WARNING) + { + //check if combination field is canonical (all remaining bits are 0) + auto remaining_combination_bits = (r.combination & ((1 << (w - 1)) - 1)); + std::assert_warn(remaining_combination_bits == 0, std::format("NaN - remaining combination field bits not canonical! Expected 0, got {}", remaining_combination_bits)); + //TODO: also check if encoding of the payload is canonical + } return is_signaling ? "sNaN" : "qNaN"; } else if((r.combination >> w) & 0b11111 == 0b11110) { //Inf's //Note: Inf might not be canonical -#ifndef IEEE754_SUPPRESS_WARNING - //check if combination field is canonical (all remaining bits are 0) - auto remaining_combination_bits = r.combination & ((1 << w) - 1); - std::assert_warn(remaining_combination_bits == 0, std::format("Inf - remaining combination field bits not canonical! Expected 0, got {}", remaining_combination_bits)); - std::assert_warn(r.significand == 0, std::format("Inf - significand not canonical! Expected 0, got {}", r.significand)); -#endif + if(!IEEE754_SUPPRESS_WARNING) + { + //check if combination field is canonical (all remaining bits are 0) + auto remaining_combination_bits = r.combination & ((1 << w) - 1); + std::assert_warn(remaining_combination_bits == 0, std::format("Inf - remaining combination field bits not canonical! Expected 0, got {}", remaining_combination_bits)); + std::assert_warn(r.significand == 0, std::format("Inf - significand not canonical! Expected 0, got {}", r.significand)); + } return r.sign ? "-Inf" : "Inf"; } else if(r.encoding == decimal_encoding::binary) @@ -121,9 +120,10 @@ namespace ieee754 if((full_significand == 0) || (full_significand > max_value)) { //0s -#ifndef IEEE754_SUPPRESS_WARNING - std::assert_warn(full_significand == 0, std::format("0 - significand not canonical! Expected < {}, got {}", max_value, full_significand)); -#endif + if(!IEEE754_SUPPRESS_WARNING) + { + std::assert_warn(full_significand == 0, std::format("0 - significand not canonical! Expected < {}, got {}", max_value, full_significand)); + } return r.sign ? "-0" : "0"; } @@ -256,5 +256,4 @@ namespace ieee754 using decimal192 = decimal<21, 170, encoding>; using decimal224 = decimal<23, 200, encoding>; using decimal256 = decimal<25, 230, encoding>; -} } \ No newline at end of file From bd178746a7a90d20069642d2a5f4b5d6e9a0179e Mon Sep 17 00:00:00 2001 From: BobSmun <6492115+BobSmun@users.noreply.github.com> Date: Sun, 1 Dec 2024 13:18:28 +0800 Subject: [PATCH 4/4] Make sealed again --- includes/type/ieee754_binary.pat | 1 + includes/type/ieee754_decimal.pat | 1 + 2 files changed, 2 insertions(+) diff --git a/includes/type/ieee754_binary.pat b/includes/type/ieee754_binary.pat index af990ddc..71906d10 100644 --- a/includes/type/ieee754_binary.pat +++ b/includes/type/ieee754_binary.pat @@ -39,6 +39,7 @@ namespace auto type::ieee754 } } [[ + sealed, bitfield_order(std::core::BitfieldOrder::MostToLeastSignificant, 1 + exponent_width + significand_width), format_read("type::ieee754::impl::format_binary"), transform("type::ieee754::impl::transform_binary") diff --git a/includes/type/ieee754_decimal.pat b/includes/type/ieee754_decimal.pat index d00b6fa2..738f5406 100644 --- a/includes/type/ieee754_decimal.pat +++ b/includes/type/ieee754_decimal.pat @@ -47,6 +47,7 @@ namespace auto type::ieee754 std::assert((encoding == decimal_encoding::decimal) || ((significand_width + 4) <= 128), std::format("Invalid significand_width for binary encoding! Expected <= 120, got {}", significand_width)); } [[ + sealed, bitfield_order(std::core::BitfieldOrder::MostToLeastSignificant, 1 + combination_width + significand_width), format_read("type::ieee754::impl::format_decimal") ]];