numera/number/integer/z/ops/
mul.rs

1// numera::number::integer::z::ops::mul
2//
3//! Implement the multiplication operations, and the Product trait.
4//
5
6use crate::number::{integer::*, traits::ConstOne};
7use core::{
8    iter::Product,
9    ops::{Mul, MulAssign},
10};
11use devela::paste;
12
13macro_rules! impl_integer_mul {
14    // impl Mul ops for multiple integer types
15    //
16    // # Args
17    // $t: integer base name. e.g. Integer
18    // $p: inner primitive base name. e.g. i
19    // $b: integer and primitive bitsize. e.g. 8
20    ( $($t:ident + $p:ident + $b:literal, cast: $bcast:literal);+ ) => {
21        $( impl_integer_mul![mul: $t + $p + $b]; )+
22    };
23
24    // multiplication operations
25    //
26    // impl variants:
27    // - mul
28    // - checked_mul_
29    // - saturating_mul_
30    // - wrapping_mul_
31    // - overflowing_mul_
32    // - modular_mul_ TODO
33    // - modular_counting_mul_ TODO
34    (mul: $t:ident + $p:ident + $b:literal) => { paste! {
35        impl Mul<[<$t$b>]> for [<$t$b>] {
36            /// Performs the `*` operation.
37            ///
38            /// # Panics
39            /// Panics in debug, on overflow.
40            /// While in release, it performs two's complement wrapping.
41            type Output = [<$t$b>];
42            #[inline]
43            fn mul(self, rhs: [<$t$b>]) -> Self::Output {
44                self.mul(rhs)
45            }
46        }
47        impl MulAssign for [<$t$b>] {
48            /// Performs the `*=` operation.
49            ///
50            /// # Panics
51            /// Panics in debug, on overflow.
52            /// While in release, it performs two's complement wrapping.
53            #[inline]
54            fn mul_assign(&mut self, rhs: [<$t$b>]) {
55                self.0 *= rhs.0;
56            }
57        }
58
59        impl Product for [<$t$b>] {
60            fn product<I: Iterator<Item=Self>>(iter: I) -> Self {
61                iter.fold(
62                    [<$t$b>]::ONE,
63                    |a, b| a * b,
64                )
65            }
66        }
67        impl<'a> Product<&'a [<$t$b>]> for [<$t$b>] {
68            fn product<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
69                iter.fold(
70                    [<$t$b>]::ONE,
71                    |a, b| a * *b,
72                )
73            }
74        }
75
76        /// # Multiplication
77        impl [<$t$b>] {
78            /// Integer multiplication.
79            ///
80            /// # Panics
81            /// Panics in debug, on overflow.
82            /// While in release, it performs two's complement wrapping.
83            #[inline]
84            #[must_use]
85            pub const fn mul(self, rhs: [<$t$b>]) -> [<$t$b>] {
86                Self(self.0 * rhs.0)
87            }
88
89            /// Checked integer multiplication.
90            ///
91            /// Returns `None` on overflow.
92            #[inline]
93            #[must_use]
94            pub const fn checked_mul(self, rhs: [<$t$b>]) -> Option<[<$t$b>]> {
95                if let Some(result) = self.0.checked_mul(rhs.0) {
96                    Some(Self(result))
97                } else {
98                    None
99                }
100            }
101
102            /// Saturating multiplication.
103            /// Computes `self + rhs`, saturating at the numeric bounds instead of overflowing.
104            #[inline]
105            #[must_use]
106            pub const fn saturating_mul(self, rhs: [<$t$b>]) -> [<$t$b>] {
107                Self(self.0.saturating_mul(rhs.0))
108            }
109
110            /// Wrapping (modular) multiplication.
111            /// Computes `self + rhs`, wrapping around at the boundary of the type.
112            #[inline]
113            #[must_use]
114            pub const fn wrapping_mul(self, rhs: [<$t$b>]) -> [<$t$b>] {
115                Self(self.0.wrapping_mul(rhs.0))
116            }
117
118            /// Overflowing multiplication.
119            ///
120            /// Returns a tuple of the multiplication along with a boolean indicating
121            /// whether an arithmetic overflow would occur. If an overflow would
122            /// have occurred then the wrapped value is returned.
123            #[inline]
124            #[must_use]
125            pub const fn overflowing_mul(self, rhs: [<$t$b>]) -> ([<$t$b>], bool) {
126                let (result, overflown) = self.0.overflowing_mul(rhs.0);
127                (Self(result), overflown)
128            }
129
130            // /// Modular multiplication with a custom `modulo`.
131            // #[inline]
132            // #[must_use]
133            // // TEST
134            // pub const fn modular_mul(self, rhs: [<$t$b>], modulo: [<$t$b>]) -> [<$t$b>] {
135            //     self.mul(rhs).rem_euclid(modulo)
136            //
137            // }
138        }
139    }};
140
141}
142
143impl_integer_mul![
144    Integer+i+8, cast:16;
145    Integer+i+16, cast:32;
146    Integer+i+32, cast:64;
147    Integer+i+64, cast:128;
148    Integer+i+128, cast:128
149];
150
151#[cfg(feature = "dashu-int")]
152mod big {
153    use super::*;
154
155    impl Mul<IntegerBig> for IntegerBig {
156        type Output = IntegerBig;
157        /// Performs the `*` operation.
158        #[inline]
159        #[must_use]
160        fn mul(self, rhs: IntegerBig) -> Self::Output {
161            Self(self.0 * rhs.0)
162        }
163    }
164    impl MulAssign for IntegerBig {
165        /// Performs the `*=` operation.
166        #[inline]
167        fn mul_assign(&mut self, rhs: IntegerBig) {
168            self.0 *= rhs.0;
169        }
170    }
171
172    impl Product for IntegerBig {
173        fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
174            iter.fold(IntegerBig::new(1), |a, b| a * b)
175        }
176    }
177    impl<'a> Product<&'a IntegerBig> for IntegerBig {
178        fn product<I: Iterator<Item = &'a Self>>(iter: I) -> Self {
179            iter.fold(
180                IntegerBig::new(1),
181                |a, b| a * b.clone(), // CHECK performance
182            )
183        }
184    }
185}