Skip to content

arrow-buffer: i256: implement ilog via i256 crate#9453

Open
theirix wants to merge 4 commits intoapache:mainfrom
theirix:i256-pow
Open

arrow-buffer: i256: implement ilog via i256 crate#9453
theirix wants to merge 4 commits intoapache:mainfrom
theirix:i256-pow

Conversation

@theirix
Copy link
Contributor

@theirix theirix commented Feb 20, 2026

Which issue does this PR close?

Rationale for this change

Implementation of integer logarithms via i256 crate. There is no matching num_traits trait, but this implementation provides a good motivation for such a trait.

What changes are included in this PR?

  • A new dependency on i256 crate
  • Checked methods (log, log2, log10)
  • Unchecked methods (panic by design)

Are these changes tested?

  • Unit tests

Are there any user-facing changes?

@github-actions github-actions bot added the arrow Changes to the arrow crate label Feb 20, 2026
@theirix theirix marked this pull request as ready for review February 20, 2026 22:19
/// Returns `None` if `self` is less than or equal to zero, or if `base` is less than 2.
#[inline]
pub fn checked_ilog(self, base: i256) -> Option<u32> {
if self <= Self::ZERO || base < i256::from(2) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since these invariants are checked by the call to ExtI256::checked_ilog anyway, what's the point of restating the logic here? The to_ext_i256 calls should be no-ops anyway.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason was to place checks closer to the caller. For procmacros of i256, it's less clear from the source code, but the documentation explicitly lists the required checks, and we repeat them in a docstring. Removed extra code.

/// Returns `None` if `self` is less than or equal to zero.
#[inline]
pub fn checked_ilog10(self) -> Option<u32> {
// Switch to I256::checked_ilog10 when I256 switches MSRV
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why can't it be used now?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

checked_ilog10 is literally commented out in i256 code: Alexhuszagh/i256-rs@85c0bb1/src/int/checked.rs#L102

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I only checked checked_ilog2. My mistake :)

/// Returns `None` if `self` is less than or equal to zero.
#[inline]
pub fn checked_ilog2(self) -> Option<u32> {
// Switch to I256::checked_ilog2 when I256 switches MSRV
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above: why not now?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For checked_ilog2 - it exists, updated the call.

// log10 should be 76 or 77
let result = large.checked_ilog(i256::from(10));
assert!(result.is_some());
assert!(result.unwrap() >= 76 && result.unwrap() <= 77);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why can't an assert_eq! be used here? Surely the result is deterministic?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

arrow Changes to the arrow crate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

arrow-buffer: implement log for i256

2 participants