Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] umul192_lower128 can error on due to overflow on addition #84

Closed
Alexhuszagh opened this issue May 14, 2022 · 0 comments
Closed
Assignees
Labels
bug Something isn't working high priority High priority

Comments

@Alexhuszagh
Copy link
Owner

Description

The function umul192_lower128, used in writing floats, can overflow in rare circumstances in the following logic:

hi + (hi_lo >> 64) as u64

The wrapping is actually desired, as shown by the failing test case.

#[inline(always)]
pub const fn umul192_lower128(x: u64, yhi: u64, ylo: u64) -> (u64, u64) {
    let hi = x.wrapping_mul(yhi);
    let hi_lo = x as u128 * ylo as u128;
    (hi + (hi_lo >> 64) as u64, hi_lo as u64)
}

umul192_lower128(15966911296221875, 0xcccccccccccccccc, 0xcccccccccccccccd);

In Python code, we have the same logic with the following:

>>> x = 15966911296221875
>>> yhi = 0xcccccccccccccccc
>>> ylo = 0xcccccccccccccccd
>>> y = (yhi << 64) + ylo
>>> z = x * y
>>> print(z & (2**128 - 1))
3193382259244375

This means hi + (hi_lo >> 64) as u64 is expected to wrap.

Prerequisites

Here are a few things you should provide to help me understand the issue:

  • Rust version: rustc 1.62.0-nightly (6dd68402c 2022-05-11)
  • lexical version: lexical-write-float v0.8.4
  • lexical compilation features used: default

Test case

Please provide a short, complete (with crate import, etc) test case for
the issue, showing clearly the expected and obtained results.

Example test case:

#[inline(always)]
pub const fn umul192_lower128(x: u64, yhi: u64, ylo: u64) -> (u64, u64) {
    let hi = x.wrapping_mul(yhi);
    let hi_lo = x as u128 * ylo as u128;
    (hi + (hi_lo >> 64) as u64, hi_lo as u64)
}

fn main() {
    umul192_lower128(15966911296221875, 14757395258967641292, 14757395258967641293);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working high priority High priority
Projects
None yet
Development

No branches or pull requests

1 participant