dashu_ratio/
mul.rs

1use core::ops::{Mul, MulAssign};
2
3use dashu_base::Gcd;
4use dashu_int::{IBig, UBig};
5
6use crate::{
7    helper_macros::{impl_binop_assign_by_taking, impl_binop_with_int, impl_binop_with_macro},
8    rbig::{RBig, Relaxed},
9    repr::Repr,
10};
11
12impl Repr {
13    #[inline]
14    fn sqr(&self) -> Self {
15        Self {
16            numerator: self.numerator.sqr().into(),
17            denominator: self.denominator.sqr(),
18        }
19    }
20
21    #[inline]
22    fn cubic(&self) -> Self {
23        Self {
24            numerator: self.numerator.cubic(),
25            denominator: self.denominator.cubic(),
26        }
27    }
28
29    #[inline]
30    fn pow(&self, n: usize) -> Self {
31        Self {
32            numerator: self.numerator.pow(n),
33            denominator: self.denominator.pow(n),
34        }
35    }
36}
37
38impl RBig {
39    /// Compute the square of the number (`self * self`).
40    ///
41    /// # Examples
42    ///
43    /// ```
44    /// # use dashu_ratio::RBig;
45    /// let a = RBig::from_parts(2.into(), 3u8.into());
46    /// let a2 = RBig::from_parts(4.into(), 9u8.into());
47    /// assert_eq!(a.sqr(), a2);
48    /// ```
49    #[inline]
50    pub fn sqr(&self) -> Self {
51        Self(self.0.sqr())
52    }
53
54    /// Compute the cubic of the number (`self * self * self`).
55    ///
56    /// # Examples
57    ///
58    /// ```
59    /// # use dashu_ratio::RBig;
60    /// let a = RBig::from_parts(2.into(), 3u8.into());
61    /// let a3 = RBig::from_parts(8.into(), 27u8.into());
62    /// assert_eq!(a.cubic(), a3);
63    /// ```
64    #[inline]
65    pub fn cubic(&self) -> Self {
66        Self(self.0.cubic())
67    }
68
69    /// Raise this number to a power of `n`.
70    ///
71    /// # Examples
72    ///
73    /// ```
74    /// # use dashu_ratio::RBig;
75    /// let a = RBig::from_parts(2.into(), 3u8.into());
76    /// let a5 = RBig::from_parts(32.into(), 243u8.into());
77    /// assert_eq!(a.pow(5), a5);
78    /// ```
79    #[inline]
80    pub fn pow(&self, n: usize) -> Self {
81        Self(self.0.pow(n))
82    }
83}
84
85macro_rules! impl_mul_with_rbig {
86    (
87        $a:ident, $b:ident, $c:ident, $d:ident,
88        $ra:ident, $rb:ident, $rc:ident, $rd:ident, $method:ident
89    ) => {{
90        // a/b * c/d = (ac)/gcd(a,d)/gcd(b,c)/(bd)
91        let g_ad = $ra.gcd($rd);
92        let g_bc = $rb.gcd($rc);
93        RBig(Repr {
94            numerator: ($a / &g_ad).$method($c / &g_bc),
95            denominator: ($b / g_bc).$method($d / g_ad),
96        })
97    }};
98}
99
100impl_binop_with_macro!(impl Mul, mul, impl_mul_with_rbig);
101impl_binop_assign_by_taking!(impl MulAssign for RBig, mul_assign, mul);
102
103impl Relaxed {
104    /// Compute the square of the number (`self * self`).
105    ///
106    /// See [RBig::sqr] for details.
107    #[inline]
108    pub fn sqr(&self) -> Self {
109        Self(self.0.sqr())
110    }
111
112    /// Compute the cubic of the number (`self * self * self`).
113    ///
114    /// See [RBig::cubic] for details.
115    #[inline]
116    pub fn cubic(&self) -> Self {
117        Self(self.0.cubic())
118    }
119
120    /// Raise this number to a power of `n`.
121    ///
122    /// See [RBig::pow] for details.
123    #[inline]
124    pub fn pow(&self, n: usize) -> Self {
125        Self(self.0.pow(n))
126    }
127}
128
129macro_rules! impl_mul_with_relaxed {
130    (
131        $a:ident, $b:ident, $c:ident, $d:ident,
132        $ra:ident, $rb:ident, $rc:ident, $rd:ident, $method:ident
133    ) => {{
134        let _unused = ($ra, $rb, $rc, $rd);
135        Relaxed::from_parts($a.$method($c), $b.$method($d))
136    }};
137}
138impl_binop_with_macro!(impl Mul for Relaxed, mul, impl_mul_with_relaxed);
139impl_binop_assign_by_taking!(impl MulAssign for Relaxed, mul_assign, mul);
140
141macro_rules! impl_mul_int_with_rbig {
142    (
143        $a:ident, $b:ident, $i:ident,
144        $ra:ident, $rb:ident, $ri:ident, $method:ident
145    ) => {{
146        let _unused = ($ra, $rb, $ri);
147        let g = $rb.gcd($ri);
148        RBig(Repr {
149            numerator: $a.$method($i / &g),
150            denominator: $b / g,
151        })
152    }};
153}
154impl_binop_with_int!(impl Mul<UBig>, mul, impl_mul_int_with_rbig);
155impl_binop_with_int!(impl Mul<IBig>, mul, impl_mul_int_with_rbig);
156impl_binop_with_int!(impl Mul for UBig, mul, impl_mul_int_with_rbig);
157impl_binop_with_int!(impl Mul for IBig, mul, impl_mul_int_with_rbig);
158
159macro_rules! impl_mul_int_with_relaxed {
160    (
161        $a:ident, $b:ident, $i:ident,
162        $ra:ident, $rb:ident, $ri:ident, $method:ident
163    ) => {{
164        let _unused = ($ra, $rb, $ri);
165        Relaxed::from_parts($a.$method($i), $b)
166    }};
167}
168impl_binop_with_int!(impl Mul<UBig>, mul, Relaxed, impl_mul_int_with_relaxed);
169impl_binop_with_int!(impl Mul<IBig>, mul, Relaxed, impl_mul_int_with_relaxed);
170impl_binop_with_int!(impl Mul for UBig, mul, Relaxed, impl_mul_int_with_relaxed);
171impl_binop_with_int!(impl Mul for IBig, mul, Relaxed, impl_mul_int_with_relaxed);