1use dashu_int::{IBig, UBig};
2
3use crate::{
4 error::{assert_finite, assert_finite_operands},
5 fbig::FBig,
6 helper_macros,
7 repr::{Context, Repr, Word},
8 round::{Round, Rounded},
9};
10use core::ops::{Mul, MulAssign};
11
12impl<'l, 'r, R: Round, const B: Word> Mul<&'r FBig<R, B>> for &'l FBig<R, B> {
13 type Output = FBig<R, B>;
14
15 #[inline]
16 fn mul(self, rhs: &FBig<R, B>) -> Self::Output {
17 assert_finite_operands(&self.repr, &rhs.repr);
18
19 let context = Context::max(self.context, rhs.context);
20 let repr = Repr::new(
21 &self.repr.significand * &rhs.repr.significand,
22 self.repr.exponent + rhs.repr.exponent,
23 );
24 FBig::new(context.repr_round(repr).value(), context)
25 }
26}
27
28impl<'r, R: Round, const B: Word> Mul<&'r FBig<R, B>> for FBig<R, B> {
29 type Output = FBig<R, B>;
30
31 #[inline]
32 fn mul(self, rhs: &FBig<R, B>) -> Self::Output {
33 assert_finite_operands(&self.repr, &rhs.repr);
34
35 let context = Context::max(self.context, rhs.context);
36 let repr = Repr::new(
37 self.repr.significand * &rhs.repr.significand,
38 self.repr.exponent + rhs.repr.exponent,
39 );
40 FBig::new(context.repr_round(repr).value(), context)
41 }
42}
43
44impl<'l, R: Round, const B: Word> Mul<FBig<R, B>> for &'l FBig<R, B> {
45 type Output = FBig<R, B>;
46
47 #[inline]
48 fn mul(self, rhs: FBig<R, B>) -> Self::Output {
49 assert_finite_operands(&self.repr, &rhs.repr);
50
51 let context = Context::max(self.context, rhs.context);
52 let repr = Repr::new(
53 &self.repr.significand * rhs.repr.significand,
54 self.repr.exponent + rhs.repr.exponent,
55 );
56 FBig::new(context.repr_round(repr).value(), context)
57 }
58}
59
60impl<R: Round, const B: Word> Mul<FBig<R, B>> for FBig<R, B> {
61 type Output = FBig<R, B>;
62
63 #[inline]
64 fn mul(self, rhs: FBig<R, B>) -> Self::Output {
65 assert_finite_operands(&self.repr, &rhs.repr);
66
67 let context = Context::max(self.context, rhs.context);
68 let repr = Repr::new(
69 self.repr.significand * rhs.repr.significand,
70 self.repr.exponent + rhs.repr.exponent,
71 );
72 FBig::new(context.repr_round(repr).value(), context)
73 }
74}
75
76helper_macros::impl_binop_assign_by_taking!(impl MulAssign<Self>, mul_assign, mul);
77
78macro_rules! impl_mul_primitive_with_fbig {
79 ($($t:ty)*) => {$(
80 helper_macros::impl_binop_with_primitive!(impl Mul<$t>, mul);
81 helper_macros::impl_binop_assign_with_primitive!(impl MulAssign<$t>, mul_assign);
82 )*};
83}
84impl_mul_primitive_with_fbig!(u8 u16 u32 u64 u128 usize UBig i8 i16 i32 i64 i128 isize IBig);
85
86impl<R: Round, const B: Word> FBig<R, B> {
87 #[inline]
100 pub fn sqr(&self) -> Self {
101 self.context.sqr(&self.repr).value()
102 }
103
104 #[inline]
117 pub fn cubic(&self) -> Self {
118 self.context.cubic(&self.repr).value()
119 }
120}
121
122impl<R: Round> Context<R> {
123 pub fn mul<const B: Word>(&self, lhs: &Repr<B>, rhs: &Repr<B>) -> Rounded<FBig<R, B>> {
144 assert_finite_operands(lhs, rhs);
145
146 let max_precision = if self.is_limited() {
149 self.precision * 2
150 } else {
151 usize::MAX
152 };
153
154 let lhs_shrink;
155 let lhs_repr = if lhs.digits() > max_precision {
156 lhs_shrink = Context::<R>::new(max_precision).repr_round_ref(lhs).value();
157 &lhs_shrink
158 } else {
159 lhs
160 };
161
162 let rhs_shrink;
163 let rhs_repr = if rhs.digits() > max_precision {
164 rhs_shrink = Context::<R>::new(max_precision).repr_round_ref(rhs).value();
165 &rhs_shrink
166 } else {
167 rhs
168 };
169
170 let repr = Repr::new(
171 &lhs_repr.significand * &rhs_repr.significand,
172 lhs_repr.exponent + rhs_repr.exponent,
173 );
174 self.repr_round(repr).map(|v| FBig::new(v, *self))
175 }
176
177 pub fn sqr<const B: Word>(&self, f: &Repr<B>) -> Rounded<FBig<R, B>> {
194 assert_finite(f);
195
196 let max_precision = if self.is_limited() {
198 self.precision * 2
199 } else {
200 usize::MAX
201 };
202
203 let f_shrink;
204 let f_repr = if f.digits() > max_precision {
205 f_shrink = Context::<R>::new(max_precision).repr_round_ref(f).value();
206 &f_shrink
207 } else {
208 f
209 };
210
211 let repr = Repr::new(f_repr.significand.sqr().into(), 2 * f_repr.exponent);
212 self.repr_round(repr).map(|v| FBig::new(v, *self))
213 }
214
215 pub fn cubic<const B: Word>(&self, f: &Repr<B>) -> Rounded<FBig<R, B>> {
232 assert_finite(f);
233
234 let max_precision = if self.is_limited() {
236 self.precision * 3
237 } else {
238 usize::MAX
239 };
240
241 let f_shrink;
242 let f_repr = if f.digits() > max_precision {
243 f_shrink = Context::<R>::new(max_precision).repr_round_ref(f).value();
244 &f_shrink
245 } else {
246 f
247 };
248
249 let repr = Repr::new(f_repr.significand.cubic(), 3 * f_repr.exponent);
250 self.repr_round(repr).map(|v| FBig::new(v, *self))
251 }
252}