Skip to content

Commit 744463c

Browse files
committed
[libc] INT_MIN handling
Signed-off-by: Shreeyash Pandey <[email protected]>
1 parent 40cf04a commit 744463c

File tree

2 files changed

+18
-7
lines changed

2 files changed

+18
-7
lines changed

libc/src/__support/fixed_point/fx_bits.h

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222

2323
#include "fx_rep.h"
2424

25+
#include <stdio.h>
26+
2527
#ifdef LIBC_COMPILER_HAS_FIXED_POINT
2628

2729
namespace LIBC_NAMESPACE_DECL {
@@ -246,13 +248,21 @@ template <typename XType> LIBC_INLINE constexpr XType divi(int n, int d) {
246248
}
247249
bool result_is_negative = ((n < 0) != (d < 0));
248250

249-
unsigned int nv = static_cast<unsigned int>(n < 0 ? -n : n);
250-
unsigned int dv = static_cast<unsigned int>(d < 0 ? -d : d);
251-
unsigned int clz = cpp::countl_zero<unsigned int>(dv) - 1;
252-
unsigned long int scaled_val = dv << clz;
251+
int64_t n64 = static_cast<int64_t>(n);
252+
int64_t d64 = static_cast<int64_t>(d);
253+
254+
uint64_t nv = static_cast<uint64_t>(n64 < 0 ? -n64 : n64);
255+
uint64_t dv = static_cast<uint64_t>(d64 < 0 ? -d64 : d64);
256+
257+
if (d == INT_MIN) {
258+
dv = dv - 1; // Two's complement
259+
}
260+
261+
uint32_t clz = cpp::countl_zero<uint32_t>(static_cast<uint32_t>(dv)) - 1;
262+
uint64_t scaled_val = dv << clz;
253263
// Scale denominator to be in the range of [0.5,1]
254264
FXBits<long accum> d_scaled{scaled_val};
255-
unsigned long int scaled_val_n = nv << clz;
265+
uint64_t scaled_val_n = nv << clz;
256266
// Scale the numerator as much as the denominator to maintain correctness of
257267
// the original equation
258268
FXBits<long accum> n_scaled{scaled_val_n};

libc/test/src/stdfix/DivITest.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@
1111
#include "src/__support/fixed_point/fx_rep.h"
1212
#include "test/UnitTest/Test.h"
1313

14-
#include <stdio.h>
15-
1614
template <typename XType> XType get_epsilon() = delete;
1715
template <> fract get_epsilon() { return FRACT_EPSILON; }
1816
template <> unsigned fract get_epsilon() { return UFRACT_EPSILON; }
@@ -61,6 +59,9 @@ class DivITest : public LIBC_NAMESPACE::testing::Test {
6159
EXPECT_LT(func(1, INT_MAX) - 0.r, epsilon);
6260
// This results in 1.1739, which should be saturated to FRACT_MAX
6361
EXPECT_EQ(func(27, 23), FRACT_MAX);
62+
63+
EXPECT_EQ(func(INT_MIN, 1), FRACT_MIN);
64+
EXPECT_LT(func(1, INT_MIN) - 0.r, epsilon);
6465
}
6566
};
6667

0 commit comments

Comments
 (0)