Skip to content

The carry in signed carrying_mul on integers should be unsigned #90493

Open
@dzimmanck

Description

@dzimmanck

I tried this code:

// use signed carry_mul to chain two multiplies (x*y) + (x*y) >> 64
let carry: i32 = 0;
let x: i32 = 200000;
let y: i32 = 100000;
let (carry, prod) = x.carrying_mul(y, carry);
let (carry, prod) = x.carrying_mul(y, carry);

// do the calculation with larger integers
let large = i64::from(x) * i64::from(y);
let carry = large - ((large>>32)<<32);
let expected = ((large + carry)>>32) as i32;

assert_eq!(expected, prod);

I expected to see this happen: I expected the "prod" to be 5.

Instead, this happened: The product is 4 due to the carry in the first calculation being negative (overflowing) causing it to accumulate incorrectly.

Meta

rustc --version --verbose:

rustc 1.58.0-nightly (db062de72 2021-11-01)
binary: rustc
commit-hash: db062de72b0a064f45b6f86894cbdc7c0ec68844
commit-date: 2021-11-01
host: x86_64-pc-windows-msvc
release: 1.58.0-nightly
LLVM version: 13.0.0

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-bugCategory: This is a bug.T-libsRelevant to the library team, which will review and decide on the PR/issue.T-libs-apiRelevant to the library API team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions