ark_ff_macros/montgomery/
mul.rsuse quote::quote;
pub(super) fn mul_assign_impl(
can_use_no_carry_mul_opt: bool,
num_limbs: usize,
modulus_limbs: &[u64],
modulus_has_spare_bit: bool,
) -> proc_macro2::TokenStream {
let mut body = proc_macro2::TokenStream::new();
let modulus_0 = modulus_limbs[0];
if can_use_no_carry_mul_opt {
let mut default = proc_macro2::TokenStream::new();
default.extend(quote! { let mut r = [0u64; #num_limbs]; });
for i in 0..num_limbs {
default.extend(quote! {
let mut carry1 = 0u64;
r[0] = fa::mac(r[0], (a.0).0[0], (b.0).0[#i], &mut carry1);
let k = r[0].wrapping_mul(Self::INV);
let mut carry2 = 0u64;
fa::mac_discard(r[0], k, #modulus_0, &mut carry2);
});
for (j, modulus_j) in modulus_limbs.iter().enumerate().take(num_limbs).skip(1) {
let idx = j - 1;
default.extend(quote! {
r[#j] = fa::mac_with_carry(r[#j], (a.0).0[#j], (b.0).0[#i], &mut carry1);
r[#idx] = fa::mac_with_carry(r[#j], k, #modulus_j, &mut carry2);
});
}
default.extend(quote!(r[#num_limbs - 1] = carry1 + carry2;));
}
default.extend(quote!((a.0).0 = r;));
if (2..=6).contains(&num_limbs) {
body.extend(quote!({
if cfg!(all(
feature = "asm",
target_feature = "bmi2",
target_feature = "adx",
target_arch = "x86_64"
)) {
#[cfg(
all(
feature = "asm",
target_feature = "bmi2",
target_feature = "adx",
target_arch = "x86_64"
)
)]
#[allow(unsafe_code, unused_mut)]
ark_ff::x86_64_asm_mul!(#num_limbs, (a.0).0, (b.0).0);
} else {
#[cfg(
not(all(
feature = "asm",
target_feature = "bmi2",
target_feature = "adx",
target_arch = "x86_64"
))
)]
{
#default
}
}
}))
} else {
body.extend(quote!({ #default }))
}
body.extend(quote!(__subtract_modulus(a);));
} else {
let double_limbs = num_limbs * 2;
body.extend(quote! {
let mut scratch = [0u64; #double_limbs];
});
for i in 0..num_limbs {
body.extend(quote! { let mut carry = 0u64; });
for j in 0..num_limbs {
let k = i + j;
body.extend(quote!{scratch[#k] = fa::mac_with_carry(scratch[#k], (a.0).0[#i], (b.0).0[#j], &mut carry);});
}
body.extend(quote! { scratch[#i + #num_limbs] = carry; });
}
body.extend(quote!( let mut carry2 = 0u64; ));
for i in 0..num_limbs {
body.extend(quote! {
let tmp = scratch[#i].wrapping_mul(Self::INV);
let mut carry = 0u64;
fa::mac(scratch[#i], tmp, #modulus_0, &mut carry);
});
for j in 1..num_limbs {
let modulus_j = modulus_limbs[j];
let k = i + j;
body.extend(quote!(scratch[#k] = fa::mac_with_carry(scratch[#k], tmp, #modulus_j, &mut carry);));
}
body.extend(quote!(carry2 = fa::adc(&mut scratch[#i + #num_limbs], carry, carry2);));
}
body.extend(quote! {
(a.0).0 = scratch[#num_limbs..].try_into().unwrap();
});
if modulus_has_spare_bit {
body.extend(quote!(__subtract_modulus(a);));
} else {
body.extend(quote!(__subtract_modulus_with_carry(a, carry2 != 0);));
}
}
body
}