Skip to content

[WIP] Expand multiplication methods#403

Closed
dignifiedquire wants to merge 10 commits into
masterfrom
feat-expand-mul
Closed

[WIP] Expand multiplication methods#403
dignifiedquire wants to merge 10 commits into
masterfrom
feat-expand-mul

Conversation

@dignifiedquire

Copy link
Copy Markdown
Member

Currently implements karatusba and schoolbook based on num-bigint-dig.

Comment thread src/uint/add.rs
@dignifiedquire dignifiedquire force-pushed the feat-expand-mul branch 2 times, most recently from 49ae88f to 4c816cd Compare December 17, 2023 17:39
Comment thread src/uint/mul.rs
#[cfg(feature = "alloc")]
mod karatsuba;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Since this is gated under alloc and not shared with Uint, maybe just put it under uint/boxed/karatsuba.rs?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

well my goal was to have this work with Uint before merging, just trying to get the first thing working

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Aah ok. Right now sharing code involves macros like impl_schoolbook_multiplication! since without const_mut_refs there's no way to construct anything other than a const generic-sized array in a const fn

Comment on lines +1 to +38
use num_traits::Zero;

use crate::{uint::add::adc, Limb, WideWord, Word};

/// Schoolbook multiplication
pub(super) fn mul(x: &[Limb], y: &[Limb], acc: &mut [Limb]) {
for (i, xi) in x.iter().enumerate() {
mac_digit(&mut acc[i..], y, *xi);
}
}

fn mac_digit(acc: &mut [Limb], b: &[Limb], c: Limb) {
if c.is_zero() {
return;
}

let mut carry = 0;
let (a_lo, a_hi) = acc.split_at_mut(b.len());

for (a, &b) in a_lo.iter_mut().zip(b) {
*a = mac_with_carry(*a, b, c, &mut carry);
}

let mut a = a_hi.iter_mut();
while carry != 0 {
let a = a.next().expect("carry overflow during multiplication!");
*a = Limb(adc(a.0, 0, &mut carry));
}
}

#[inline]
fn mac_with_carry(a: Limb, b: Limb, c: Limb, acc: &mut WideWord) -> Limb {
*acc += a.0 as WideWord;
*acc += (b.0 as WideWord) * (c.0 as WideWord);
let lo = *acc as Word;
*acc >>= Word::BITS;
Limb(lo)
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Perhaps you could use the impl_schoolbook_multiplication! macro instead of this, so we just have one implementation?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

that didn’t work before, because I needed Wors, probably can go back now

Comment thread src/uint/add.rs
Comment on lines +138 to +145
#[inline]
pub(crate) fn adc(a: Word, b: Word, acc: &mut WideWord) -> Word {
*acc += a as WideWord;
*acc += b as WideWord;
let lo = *acc as Word;
*acc >>= Word::BITS;
lo
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Limb has an adc method you can call directly.

Also this whole module feels like implementation details of Karatsuba. Maybe move it to karatsuba.rs?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I am using parts of this in the div impl, that's why I moved it into the shared piece.

Comment thread src/limb/div.rs
///
/// (This function also matches what the x86 divide instruction does).
#[inline]
pub(crate) fn div_wide(hi: Word, lo: Word, divisor: Word) -> (Word, Word) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
pub(crate) fn div_wide(hi: Word, lo: Word, divisor: Word) -> (Word, Word) {
pub(crate) fn div_wide_vartime(hi: Word, lo: Word, divisor: Word) -> (Word, Word) {

Comment thread src/uint/boxed/div.rs
/// Division by a single word.
///
/// This function operates in variable-time.
fn div_rem_digit(&self, b: Word) -> (Self, Word) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
fn div_rem_digit(&self, b: Word) -> (Self, Word) {
fn div_rem_digit_vartime(&self, b: Word) -> (Self, Word) {

@tarcieri

Copy link
Copy Markdown
Member

Karatsuba was added in #649

@tarcieri tarcieri closed this Aug 20, 2024
@tarcieri tarcieri deleted the feat-expand-mul branch August 20, 2024 15:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants