diff --git a/AK/FixedPoint.h b/AK/FixedPoint.h index 72ddb7f5f05..144f6979142 100644 --- a/AK/FixedPoint.h +++ b/AK/FixedPoint.h @@ -419,16 +419,21 @@ struct Formatter> : StandardFormatter { ErrorOr format(FormatBuilder& builder, FixedPoint value) { u8 base; - bool upper_case; + bool upper_case = false; if (m_mode == Mode::Default || m_mode == Mode::FixedPoint) { base = 10; - upper_case = false; } else if (m_mode == Mode::Hexfloat) { base = 16; - upper_case = false; } else if (m_mode == Mode::HexfloatUppercase) { base = 16; upper_case = true; + } else if (m_mode == Mode::Binary) { + base = 2; + } else if (m_mode == Mode::BinaryUppercase) { + base = 2; + upper_case = true; + } else if (m_mode == Mode::Octal) { + base = 8; } else { VERIFY_NOT_REACHED(); } diff --git a/AK/Format.cpp b/AK/Format.cpp index a4f4250a11a..40f0a6b40c5 100644 --- a/AK/Format.cpp +++ b/AK/Format.cpp @@ -403,9 +403,10 @@ ErrorOr FormatBuilder::put_fixed_point( // FIXME: overflows (not before: fraction_value = (2^precision - 1) and precision >= 20) (use wider integer type) auto fraction = scale * fraction_value; TRY(format_builder.put_u64(fraction, base, false, upper_case, true, use_separator, Align::Right, precision)); - } else if (base == 16) { - auto fraction = fraction_value << ((4 - (precision % 4)) % 4); - TRY(format_builder.put_u64(fraction, base, false, upper_case, false, use_separator, Align::Right, precision/4 + (precision % 4 != 0), '0')); + } else if (base == 16 || base == 8 || base == 2) { + auto bits_per_character = log2(base); + auto fraction = fraction_value << ((bits_per_character - (precision % bits_per_character)) % bits_per_character); + TRY(format_builder.put_u64(fraction, base, false, upper_case, false, use_separator, Align::Right, precision / bits_per_character + (precision % bits_per_character != 0), '0')); } else { VERIFY_NOT_REACHED(); } diff --git a/Tests/AK/TestFixedPoint.cpp b/Tests/AK/TestFixedPoint.cpp index 1e080dd0f5b..a59c118225b 100644 --- a/Tests/AK/TestFixedPoint.cpp +++ b/Tests/AK/TestFixedPoint.cpp @@ -234,7 +234,18 @@ TEST_CASE(formatter) // EXPECT_EQ(DeprecatedString::formatted("{:0.30}", AK::FixedPoint<28, u64>::create_raw(1)), "0.000000003725290298461914062500"sv); EXPECT_EQ(DeprecatedString::formatted("{:a}", FixedPoint<16>(42.42)), "2a.6b85"sv); + EXPECT_EQ(DeprecatedString::formatted("{:o}", FixedPoint<16>(42.42)), "52.327024"sv); + EXPECT_EQ(DeprecatedString::formatted("{:b}", FixedPoint<16>(42.42)), "101010.01101"sv); EXPECT_EQ(DeprecatedString::formatted("{:0.10a}", FixedPoint<16>(69.69)), "45.b0a4000000"sv); + EXPECT_EQ(DeprecatedString::formatted("{:0.10o}", FixedPoint<16>(69.69)), "105.5412200000"sv); + EXPECT_EQ(DeprecatedString::formatted("{:0.10b}", FixedPoint<16>(69.69)), "1000101.1011000010"sv); + + EXPECT_EQ(DeprecatedString::formatted("{:.30o}", AK::FixedPoint<13, u64>::create_raw(1)), "0.00004"sv); + EXPECT_EQ(DeprecatedString::formatted("{:.30b}", AK::FixedPoint<13, u64>::create_raw(1)), "0.0000000000001"sv); + EXPECT_EQ(DeprecatedString::formatted("{:.30o}", AK::FixedPoint<21, u64>::create_raw(0211234567)), "21.1234567"sv); + EXPECT_EQ(DeprecatedString::formatted("{:.30b}", AK::FixedPoint<13, u64>::create_raw(0b110011011010110)), "11.001101101011"sv); + EXPECT_EQ(DeprecatedString::formatted("{:.30o}", AK::FixedPoint<11, u64>::create_raw((1ull << 11) - 1)), "0.7776"sv); + EXPECT_EQ(DeprecatedString::formatted("{:.30b}", AK::FixedPoint<11, u64>::create_raw((1ull << 11) - 1)), "0.11111111111"sv); // maximum fraction per precision rendered in hexadecimal; 1 - 2^-precision; no overflow EXPECT_EQ(DeprecatedString::formatted("{:.30a}", AK::FixedPoint<7, u64>::create_raw((1ull << 7) - 1)), "0.fe"sv);