Skip to content

Commit 77e767f

Browse files
authored
Reimplemented pow5Factor using modular inverse. (#188)
* Reimplemented pow5Factor using modular inverse. * Put back assert inadvertently removed. * Added tests for pow5Factor. * Fixed comment.
1 parent 844864a commit 77e767f

File tree

2 files changed

+44
-5
lines changed

2 files changed

+44
-5
lines changed

ryu/d2s_intrinsics.h

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -189,15 +189,14 @@ static inline uint32_t mod1e9(const uint64_t x) {
189189
#endif // defined(RYU_32_BIT_PLATFORM)
190190

191191
static inline uint32_t pow5Factor(uint64_t value) {
192+
const uint64_t m_inv_5 = 14757395258967641293u; // 5 * m_inv_5 = 1 (mod 2^64)
193+
const uint64_t n_div_5 = 3689348814741910323u; // #{ n | n = 0 (mod 2^64) } = 2^64 / 5
192194
uint32_t count = 0;
193195
for (;;) {
194196
assert(value != 0);
195-
const uint64_t q = div5(value);
196-
const uint32_t r = ((uint32_t) value) - 5 * ((uint32_t) q);
197-
if (r != 0) {
197+
value *= m_inv_5;
198+
if (value > n_div_5)
198199
break;
199-
}
200-
value = q;
201200
++count;
202201
}
203202
return count;

ryu/tests/d2s_intrinsics_test.cc

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,43 @@ TEST(D2sIntrinsicsTest, mod1e9) {
4343
TEST(D2sIntrinsicsTest, shiftRight128) {
4444
EXPECT_EQ(0x100000000ull, shiftright128(0x1ull, 0x1ull, 32));
4545
}
46+
47+
TEST(D2sIntrinsicsTest, pow5Factor) {
48+
EXPECT_EQ(0u, pow5Factor(1ull));
49+
EXPECT_EQ(0u, pow5Factor(2ull));
50+
EXPECT_EQ(0u, pow5Factor(3ull));
51+
EXPECT_EQ(0u, pow5Factor(4ull));
52+
EXPECT_EQ(1u, pow5Factor(5ull));
53+
EXPECT_EQ(0u, pow5Factor(6ull));
54+
EXPECT_EQ(0u, pow5Factor(7ull));
55+
EXPECT_EQ(0u, pow5Factor(8ull));
56+
EXPECT_EQ(0u, pow5Factor(9ull));
57+
EXPECT_EQ(1u, pow5Factor(10ull));
58+
59+
EXPECT_EQ(0u, pow5Factor(12ull));
60+
EXPECT_EQ(0u, pow5Factor(14ull));
61+
EXPECT_EQ(0u, pow5Factor(16ull));
62+
EXPECT_EQ(0u, pow5Factor(18ull));
63+
EXPECT_EQ(1u, pow5Factor(20ull));
64+
65+
EXPECT_EQ(2u, pow5Factor(5*5ull));
66+
EXPECT_EQ(3u, pow5Factor(5*5*5ull));
67+
EXPECT_EQ(4u, pow5Factor(5*5*5*5ull));
68+
EXPECT_EQ(5u, pow5Factor(5*5*5*5*5ull));
69+
EXPECT_EQ(6u, pow5Factor(5*5*5*5*5*5ull));
70+
EXPECT_EQ(7u, pow5Factor(5*5*5*5*5*5*5ull));
71+
EXPECT_EQ(8u, pow5Factor(5*5*5*5*5*5*5*5ull));
72+
EXPECT_EQ(9u, pow5Factor(5*5*5*5*5*5*5*5*5ull));
73+
EXPECT_EQ(10u, pow5Factor(5*5*5*5*5*5*5*5*5*5ull));
74+
75+
EXPECT_EQ(0u, pow5Factor(42ull));
76+
EXPECT_EQ(1u, pow5Factor(42*5ull));
77+
EXPECT_EQ(2u, pow5Factor(42*5*5ull));
78+
EXPECT_EQ(3u, pow5Factor(42*5*5*5ull));
79+
EXPECT_EQ(4u, pow5Factor(42*5*5*5*5ull));
80+
EXPECT_EQ(5u, pow5Factor(42*5*5*5*5*5ull));
81+
82+
EXPECT_EQ(27u, pow5Factor(7450580596923828125ull)); // 5^27, largest power of 5 < 2^64.
83+
EXPECT_EQ(1u, pow5Factor(18446744073709551615ull)); // 2^64 - 1, largest multiple of 5 < 2^64.
84+
EXPECT_EQ(0u, pow5Factor(18446744073709551614ull)); // 2^64 - 2, largest non-multiple of 5 < 2^64.
85+
}

0 commit comments

Comments
 (0)