Add support for scaling numbers by primitive types.
This commit is contained in:
121
src/signed/scale.rs
Normal file
121
src/signed/scale.rs
Normal file
@@ -0,0 +1,121 @@
|
||||
macro_rules! scale_impls
|
||||
{
|
||||
($base: ident, $big: ident) => {
|
||||
scale_impls!($base, $big, u8);
|
||||
scale_impls!($base, $big, u16);
|
||||
scale_impls!($base, $big, u32);
|
||||
scale_impls!($base, $big, u64);
|
||||
scale_impls!($base, $big, usize);
|
||||
|
||||
scale_impls!($base, $big, scaled i8);
|
||||
scale_impls!($base, $big, scaled i16);
|
||||
scale_impls!($base, $big, scaled i32);
|
||||
scale_impls!($base, $big, scaled i64);
|
||||
scale_impls!($base, $big, scaled isize);
|
||||
};
|
||||
($base: ident, $big: ident, $prim: ident) => {
|
||||
impl Mul<$prim> for $base {
|
||||
type Output = $big;
|
||||
|
||||
fn mul(self, factor: $prim) -> $big {
|
||||
&self * factor
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Mul<$prim> for &'a $base {
|
||||
type Output = $big;
|
||||
|
||||
fn mul(self, factor: $prim) -> $big {
|
||||
let mut res = $big::zero();
|
||||
scale(&mut res.value.value, &self.value.value, factor as u64);
|
||||
res.negative = self.negative && !res.value.is_zero();
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<$base> for $prim {
|
||||
type Output = $big;
|
||||
|
||||
fn mul(self, rhs: $base) -> $big {
|
||||
rhs.mul(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Mul<&'a $base> for $prim {
|
||||
type Output = $big;
|
||||
|
||||
fn mul(self, rhs: &$base) -> $big {
|
||||
rhs.mul(self)
|
||||
}
|
||||
}
|
||||
};
|
||||
($base: ident, $big: ident, scaled $prim: ident) => {
|
||||
impl Mul<$prim> for $base {
|
||||
type Output = $big;
|
||||
|
||||
fn mul(self, factor: $prim) -> $big {
|
||||
&self * factor
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Mul<$prim> for &'a $base {
|
||||
type Output = $big;
|
||||
|
||||
fn mul(self, factor: $prim) -> $big {
|
||||
let mut res = $big::zero();
|
||||
scale(&mut res.value.value, &self.value.value, factor.abs() as u64);
|
||||
res.negative = (self.negative ^ (factor < 0)) && !res.value.is_zero();
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<$base> for $prim {
|
||||
type Output = $big;
|
||||
|
||||
fn mul(self, rhs: $base) -> $big {
|
||||
rhs.mul(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Mul<&'a $base> for $prim {
|
||||
type Output = $big;
|
||||
|
||||
fn mul(self, rhs: &$base) -> $big {
|
||||
rhs.mul(self)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
macro_rules! generate_sigscale_tests
|
||||
{
|
||||
($name: ident, $uname: ident, $lname: ident, $big: ident, $ubig: ident) => {
|
||||
#[test]
|
||||
fn $lname() {
|
||||
generate_sigscale_tests!(body $name, $uname, $lname, $big, $ubig);
|
||||
}
|
||||
};
|
||||
(ignore $name: ident, $uname:ident, $lname: ident, $big: ident, $ubig: ident) => {
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn $lname() {
|
||||
generate_sigscale_tests!(body $name, $uname, $lname, $big, $ubig);
|
||||
}
|
||||
};
|
||||
(body $name: ident, $uname: ident, $lname: ident, $big: ident, $ubig: ident) => {
|
||||
let fname = build_test_path("sigscale", stringify!($name));
|
||||
run_test(fname.to_string(), 3, |case| {
|
||||
let (nega, abytes) = case.get("a").unwrap();
|
||||
let (negb, bbytes) = case.get("b").unwrap();
|
||||
let (negc, cbytes) = case.get("c").unwrap();
|
||||
|
||||
let a = $name::new(*nega, $uname::from_bytes(abytes));
|
||||
let bbig = $name::new(*negb, $uname::from_bytes(bbytes));
|
||||
let c = $big::new(*negc, $ubig::from_bytes(cbytes));
|
||||
let b = i64::from(&bbig);
|
||||
let res = &a * b;
|
||||
assert_eq!(c, res);
|
||||
});
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user