Skip to content

Commit 74ead49

Browse files
committed
Optimize .ilog({2,10}) to .ilog{2,10}()
Switch to faster methods when base is statically known.
1 parent 6ba0ce4 commit 74ead49

File tree

1 file changed

+56
-10
lines changed

1 file changed

+56
-10
lines changed

library/core/src/num/uint_macros.rs

Lines changed: 56 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1491,17 +1491,19 @@ macro_rules! uint_impl {
14911491
without modifying the original"]
14921492
#[inline]
14931493
pub const fn checked_ilog(self, base: Self) -> Option<u32> {
1494-
if self <= 0 || base <= 1 {
1495-
None
1496-
} else if self < base {
1497-
Some(0)
1498-
} else {
1499-
// Since base >= self, n >= 1
1494+
// Preconditions for calling inner function `slow_ilog`:
1495+
//
1496+
// 1: base >= 2
1497+
// 2: x >= 1
1498+
// 3: x >= base
1499+
#[inline(always)]
1500+
const fn slow_ilog(x: $SelfT, base: $SelfT) -> u32 {
1501+
// Since x >= base, n >= 1
15001502
let mut n = 1;
15011503
let mut r = base;
15021504

15031505
// Optimization for 128 bit wide integers.
1504-
if Self::BITS == 128 {
1506+
if <$SelfT>::BITS == 128 {
15051507
// The following is a correct lower bound for ⌊log(base,self)⌋ because
15061508
//
15071509
// log(base,self) = log(2,self) / log(2,base)
@@ -1510,15 +1512,59 @@ macro_rules! uint_impl {
15101512
// hence
15111513
//
15121514
// ⌊log(base,self)⌋ ≥ ⌊ ⌊log(2,self)⌋ / (⌊log(2,base)⌋ + 1) ⌋ .
1513-
n = self.ilog2() / (base.ilog2() + 1);
1515+
n = x.ilog2() / (base.ilog2() + 1);
15141516
r = base.pow(n);
15151517
}
15161518

1517-
while r <= self / base {
1519+
while r <= x / base {
15181520
n += 1;
15191521
r *= base;
15201522
}
1521-
Some(n)
1523+
n
1524+
}
1525+
1526+
if core::intrinsics::is_val_statically_known(self) {
1527+
if self <= 0 { // precondition 2
1528+
None
1529+
} else if core::intrinsics::is_val_statically_known(base) {
1530+
if base <= 1 { // precondition 1
1531+
None
1532+
} else if self < base { // precondition 3
1533+
Some(0)
1534+
} else if base == 2 {
1535+
self.checked_ilog2()
1536+
} else if base == 10 {
1537+
self.checked_ilog10()
1538+
} else { // all preconditions satisfied
1539+
Some(slow_ilog(self, base))
1540+
}
1541+
} else if base <= 1 { // precondition 1
1542+
None
1543+
} else if self < base { // precondition 3
1544+
Some(0)
1545+
} else { // all preconditions satisfied
1546+
Some(slow_ilog(self, base))
1547+
}
1548+
} else if core::intrinsics::is_val_statically_known(base) {
1549+
if base <= 1 { // precondition 1
1550+
None
1551+
} else if base == 2 {
1552+
self.checked_ilog2()
1553+
} else if base == 10 {
1554+
self.checked_ilog10()
1555+
} else if self <= 0 { // precondition 2
1556+
None
1557+
} else if self < base { // precondition 3
1558+
Some(0)
1559+
} else { // all preconditions satisfied
1560+
Some(slow_ilog(self, base))
1561+
}
1562+
} else if self <= 0 || base <= 1 { // preconditions 1 and 2
1563+
None
1564+
} else if self < base { // precondition 3
1565+
Some(0)
1566+
} else { // all preconditions satisfied
1567+
Some(slow_ilog(self, base))
15221568
}
15231569
}
15241570

0 commit comments

Comments
 (0)