From 88d07027637e3fbc7d63189be814cfea1b1c01cf Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Fri, 26 Apr 2024 17:57:35 -0400 Subject: [PATCH] AK: Make ceil_div() handle one argument being negative correctly `ceil_div(-1, 2)` used to return -1. Now it returns 0, which is the correct ceil(-0.5). (C++'s division semantics have floor semantics for numbers > 0, but ceil semantics for numbers < 0.) This will be important for the JPEG2000 decoder eventually. --- AK/StdLibExtras.h | 2 +- Tests/AK/TestStdLibExtras.cpp | 36 +++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/AK/StdLibExtras.h b/AK/StdLibExtras.h index 57c986c67c..bf91f4a387 100644 --- a/AK/StdLibExtras.h +++ b/AK/StdLibExtras.h @@ -124,7 +124,7 @@ constexpr T ceil_div(T a, U b) { static_assert(sizeof(T) == sizeof(U)); T result = a / b; - if ((a % b) != 0) + if ((a % b) != 0 && (a > 0) == (b > 0)) ++result; return result; } diff --git a/Tests/AK/TestStdLibExtras.cpp b/Tests/AK/TestStdLibExtras.cpp index 60383f37d6..6590e20c35 100644 --- a/Tests/AK/TestStdLibExtras.cpp +++ b/Tests/AK/TestStdLibExtras.cpp @@ -20,11 +20,47 @@ TEST_CASE(ceil_div) EXPECT_EQ(ceil_div(3, 1), 3); EXPECT_EQ(ceil_div(4, 1), 4); + EXPECT_EQ(ceil_div(-0, 1), 0); + EXPECT_EQ(ceil_div(-1, 1), -1); + EXPECT_EQ(ceil_div(-2, 1), -2); + EXPECT_EQ(ceil_div(-3, 1), -3); + EXPECT_EQ(ceil_div(-4, 1), -4); + + EXPECT_EQ(ceil_div(0, -1), 0); + EXPECT_EQ(ceil_div(1, -1), -1); + EXPECT_EQ(ceil_div(2, -1), -2); + EXPECT_EQ(ceil_div(3, -1), -3); + EXPECT_EQ(ceil_div(4, -1), -4); + + EXPECT_EQ(ceil_div(-0, -1), 0); + EXPECT_EQ(ceil_div(-1, -1), 1); + EXPECT_EQ(ceil_div(-2, -1), 2); + EXPECT_EQ(ceil_div(-3, -1), 3); + EXPECT_EQ(ceil_div(-4, -1), 4); + EXPECT_EQ(ceil_div(0, 2), 0); EXPECT_EQ(ceil_div(1, 2), 1); EXPECT_EQ(ceil_div(2, 2), 1); EXPECT_EQ(ceil_div(3, 2), 2); EXPECT_EQ(ceil_div(4, 2), 2); + + EXPECT_EQ(ceil_div(-0, 2), 0); + EXPECT_EQ(ceil_div(-1, 2), 0); + EXPECT_EQ(ceil_div(-2, 2), -1); + EXPECT_EQ(ceil_div(-3, 2), -1); + EXPECT_EQ(ceil_div(-4, 2), -2); + + EXPECT_EQ(ceil_div(0, -2), 0); + EXPECT_EQ(ceil_div(1, -2), 0); + EXPECT_EQ(ceil_div(2, -2), -1); + EXPECT_EQ(ceil_div(3, -2), -1); + EXPECT_EQ(ceil_div(4, -2), -2); + + EXPECT_EQ(ceil_div(-0, -2), 0); + EXPECT_EQ(ceil_div(-1, -2), 1); + EXPECT_EQ(ceil_div(-2, -2), 1); + EXPECT_EQ(ceil_div(-3, -2), 2); + EXPECT_EQ(ceil_div(-4, -2), 2); } TEST_CASE(mix)