4

I was wondering about this code:

#[inline(always)]
pub fn multiply_u128<T>(a: T, b: T, result: &mut[u64])  {
    let r = a as u128 * b as u128;
    //fill result with 64 bit chunks
}

it will work for integers except when T is u128. In this case we could get overflows. Is it possible to make this function work with u8, u16, u32, u64 but not u128?

Guerlando OCs
  • 1,886
  • 9
  • 61
  • 150

2 Answers2

6

Can I do C++'s SFINAE in Rust?

No, Rust's generics are resolved quite a bit differently than in C++.


The most suitable way to implement this would be with Into<u64>:

pub fn multiply_u128<T: Into<u64>>(a: T, b: T, result: &mut[u64])  {
    let r = a.into() as u128 * b.into() as u128;
    // fill result with 64 bit chunks
}

Playground. Also, if you're up to using nightly features, consider using u64::widening_mul.

kmdreko
  • 42,554
  • 6
  • 57
  • 106
2

You could introduce a trait for this purpose and only implement it for the relevant types.

pub trait NotBigUInt {
    fn as_u128(self) -> u128;
}

impl NotBigUInt for u8 {
    fn as_u128(self) -> u128 {
        self as u128
    }
}
impl NotBigUInt for u16 {
    fn as_u128(self) -> u128 {
        self as u128
    }
}
impl NotBigUInt for u32 {
    fn as_u128(self) -> u128 {
        self as u128
    }
}
impl NotBigUInt for u64 {
    fn as_u128(self) -> u128 {
        self as u128
    }
}

#[inline(always)]
pub fn multiply_u128<T: NotBigUInt>(
    a: T,
    b: T,
    result: &mut [u64],
) {
    let r = a.as_u128() * b.as_u128();
    //fill result with 64 bit chunks
    result[0] = r as u64;
}

fn main() {
    let mut r = [0_u64; 1];
    multiply_u128(1_u8, 1_u8, &mut r);
    multiply_u128(1_u16, 1_u16, &mut r);
    multiply_u128(1_u32, 1_u32, &mut r);
    multiply_u128(1_u64, 1_u64, &mut r);
    // multiply_u128(1_u128, 1_u128, &mut r);
}
prog-fh
  • 13,492
  • 1
  • 15
  • 30
  • Note that this can be made a lot less repetitive with a macro. – Aplet123 Nov 12 '21 at 23:21
  • @Aplet123 certainly, but I find the solution easier to understand when explicitly applied to a few types. Of course, once understood, it can (should) be factorised. – prog-fh Nov 12 '21 at 23:42