1use alloc::rc::Rc;
4use core::iter::{Product, Sum};
5use core::ops::{
6 Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Rem, RemAssign, Shl, ShlAssign, Shr,
7 ShrAssign, Sub, SubAssign,
8};
9
10use dashu_base::{Abs, CubicRoot, DivEuclid, DivRemEuclid, Inverse, RemEuclid, Sign, SquareRoot};
11
12use crate::fbig::FBig;
13use crate::fbig_cached::CachedFBig;
14use crate::repr::{Context, Word};
15use crate::round::Round;
16
17macro_rules! impl_cached_binop {
22 ($Op:ident, $op:ident) => {
23 impl<R: Round, const B: Word> $Op<CachedFBig<R, B>> for CachedFBig<R, B> {
24 type Output = CachedFBig<R, B>;
25 #[inline]
26 fn $op(self, rhs: CachedFBig<R, B>) -> Self::Output {
27 CachedFBig::from_fbig($Op::$op(self.fbig, rhs.fbig), &self.cache)
28 }
29 }
30 impl<'l, R: Round, const B: Word> $Op<CachedFBig<R, B>> for &'l CachedFBig<R, B> {
31 type Output = CachedFBig<R, B>;
32 #[inline]
33 fn $op(self, rhs: CachedFBig<R, B>) -> Self::Output {
34 CachedFBig::from_fbig($Op::$op(self.fbig.clone(), rhs.fbig), &self.cache)
35 }
36 }
37 impl<'r, R: Round, const B: Word> $Op<&'r CachedFBig<R, B>> for CachedFBig<R, B> {
38 type Output = CachedFBig<R, B>;
39 #[inline]
40 fn $op(self, rhs: &'r CachedFBig<R, B>) -> Self::Output {
41 CachedFBig::from_fbig($Op::$op(self.fbig, rhs.fbig.clone()), &self.cache)
42 }
43 }
44 impl<'l, 'r, R: Round, const B: Word> $Op<&'r CachedFBig<R, B>> for &'l CachedFBig<R, B> {
45 type Output = CachedFBig<R, B>;
46 #[inline]
47 fn $op(self, rhs: &'r CachedFBig<R, B>) -> Self::Output {
48 CachedFBig::from_fbig($Op::$op(self.fbig.clone(), rhs.fbig.clone()), &self.cache)
49 }
50 }
51 };
52}
53impl_cached_binop!(Add, add);
54impl_cached_binop!(Sub, sub);
55impl_cached_binop!(Mul, mul);
56impl_cached_binop!(Div, div);
57impl_cached_binop!(Rem, rem);
58
59macro_rules! impl_cached_binop_assign {
60 ($OpAssign:ident, $op_assign:ident, $Op:ident, $op:ident) => {
61 impl<R: Round, const B: Word> $OpAssign<CachedFBig<R, B>> for CachedFBig<R, B> {
62 #[inline]
63 fn $op_assign(&mut self, rhs: CachedFBig<R, B>) {
64 let res = $Op::$op(self.fbig.clone(), rhs.fbig);
65 self.fbig = res;
66 }
67 }
68 };
69}
70impl_cached_binop_assign!(AddAssign, add_assign, Add, add);
71impl_cached_binop_assign!(SubAssign, sub_assign, Sub, sub);
72impl_cached_binop_assign!(MulAssign, mul_assign, Mul, mul);
73impl_cached_binop_assign!(DivAssign, div_assign, Div, div);
74impl_cached_binop_assign!(RemAssign, rem_assign, Rem, rem);
75
76macro_rules! impl_cached_binop_one_way_with_fbig {
81 ($Op:ident, $op:ident) => {
82 impl<R: Round, const B: Word> $Op<FBig<R, B>> for CachedFBig<R, B> {
83 type Output = CachedFBig<R, B>;
84 #[inline]
85 fn $op(self, rhs: FBig<R, B>) -> Self::Output {
86 CachedFBig::from_fbig($Op::$op(self.fbig, rhs), &self.cache)
87 }
88 }
89 impl<'l, R: Round, const B: Word> $Op<FBig<R, B>> for &'l CachedFBig<R, B> {
90 type Output = CachedFBig<R, B>;
91 #[inline]
92 fn $op(self, rhs: FBig<R, B>) -> Self::Output {
93 CachedFBig::from_fbig($Op::$op(self.fbig.clone(), rhs), &self.cache)
94 }
95 }
96 impl<'r, R: Round, const B: Word> $Op<&'r FBig<R, B>> for CachedFBig<R, B> {
97 type Output = CachedFBig<R, B>;
98 #[inline]
99 fn $op(self, rhs: &FBig<R, B>) -> Self::Output {
100 CachedFBig::from_fbig($Op::$op(self.fbig, rhs.clone()), &self.cache)
101 }
102 }
103 impl<'l, 'r, R: Round, const B: Word> $Op<&'r FBig<R, B>> for &'l CachedFBig<R, B> {
104 type Output = CachedFBig<R, B>;
105 #[inline]
106 fn $op(self, rhs: &FBig<R, B>) -> Self::Output {
107 CachedFBig::from_fbig($Op::$op(self.fbig.clone(), rhs.clone()), &self.cache)
108 }
109 }
110 };
111}
112
113macro_rules! impl_cached_binop_reverse_with_fbig {
114 ($Op:ident, $op:ident) => {
115 impl<R: Round, const B: Word> $Op<CachedFBig<R, B>> for FBig<R, B> {
116 type Output = CachedFBig<R, B>;
117 #[inline]
118 fn $op(self, rhs: CachedFBig<R, B>) -> Self::Output {
119 CachedFBig::from_fbig($Op::$op(self, rhs.fbig), &rhs.cache)
120 }
121 }
122 impl<'l, R: Round, const B: Word> $Op<CachedFBig<R, B>> for &'l FBig<R, B> {
123 type Output = CachedFBig<R, B>;
124 #[inline]
125 fn $op(self, rhs: CachedFBig<R, B>) -> Self::Output {
126 CachedFBig::from_fbig($Op::$op(self.clone(), rhs.fbig), &rhs.cache)
127 }
128 }
129 impl<'r, R: Round, const B: Word> $Op<&'r CachedFBig<R, B>> for FBig<R, B> {
130 type Output = CachedFBig<R, B>;
131 #[inline]
132 fn $op(self, rhs: &CachedFBig<R, B>) -> Self::Output {
133 CachedFBig::from_fbig($Op::$op(self, rhs.fbig.clone()), &rhs.cache)
134 }
135 }
136 impl<'l, 'r, R: Round, const B: Word> $Op<&'r CachedFBig<R, B>> for &'l FBig<R, B> {
137 type Output = CachedFBig<R, B>;
138 #[inline]
139 fn $op(self, rhs: &CachedFBig<R, B>) -> Self::Output {
140 CachedFBig::from_fbig($Op::$op(self.clone(), rhs.fbig.clone()), &rhs.cache)
141 }
142 }
143 };
144}
145
146impl_cached_binop_one_way_with_fbig!(Add, add);
147impl_cached_binop_one_way_with_fbig!(Sub, sub);
148impl_cached_binop_one_way_with_fbig!(Mul, mul);
149impl_cached_binop_one_way_with_fbig!(Div, div);
150impl_cached_binop_one_way_with_fbig!(Rem, rem);
151
152impl_cached_binop_reverse_with_fbig!(Add, add);
153impl_cached_binop_reverse_with_fbig!(Sub, sub);
154impl_cached_binop_reverse_with_fbig!(Mul, mul);
155impl_cached_binop_reverse_with_fbig!(Div, div);
156impl_cached_binop_reverse_with_fbig!(Rem, rem);
157
158macro_rules! impl_cached_binop_assign_with_fbig {
161 ($OpAssign:ident, $op_assign:ident, $Op:ident, $op:ident) => {
162 impl<R: Round, const B: Word> $OpAssign<FBig<R, B>> for CachedFBig<R, B> {
163 #[inline]
164 fn $op_assign(&mut self, rhs: FBig<R, B>) {
165 self.fbig = $Op::$op(self.fbig.clone(), rhs);
166 }
167 }
168 impl<R: Round, const B: Word> $OpAssign<&FBig<R, B>> for CachedFBig<R, B> {
169 #[inline]
170 fn $op_assign(&mut self, rhs: &FBig<R, B>) {
171 self.fbig = $Op::$op(self.fbig.clone(), rhs.clone());
172 }
173 }
174 };
175}
176
177impl_cached_binop_assign_with_fbig!(AddAssign, add_assign, Add, add);
178impl_cached_binop_assign_with_fbig!(SubAssign, sub_assign, Sub, sub);
179impl_cached_binop_assign_with_fbig!(MulAssign, mul_assign, Mul, mul);
180impl_cached_binop_assign_with_fbig!(DivAssign, div_assign, Div, div);
181impl_cached_binop_assign_with_fbig!(RemAssign, rem_assign, Rem, rem);
182
183macro_rules! impl_cached_binop_one_way_with_primitive {
189 ($Op:ident, $op:ident, $target:ty) => {
190 impl<R: Round, const B: Word> $Op<$target> for CachedFBig<R, B> {
191 type Output = CachedFBig<R, B>;
192 #[inline]
193 fn $op(self, rhs: $target) -> Self::Output {
194 self.$op(FBig::<R, B>::from(rhs))
195 }
196 }
197 impl<'l, R: Round, const B: Word> $Op<$target> for &'l CachedFBig<R, B> {
198 type Output = CachedFBig<R, B>;
199 #[inline]
200 fn $op(self, rhs: $target) -> Self::Output {
201 self.$op(FBig::<R, B>::from(rhs))
202 }
203 }
204 impl<'r, R: Round, const B: Word> $Op<&'r $target> for CachedFBig<R, B> {
205 type Output = CachedFBig<R, B>;
206 #[inline]
207 fn $op(self, rhs: &$target) -> Self::Output {
208 self.$op(FBig::<R, B>::from(rhs.clone()))
209 }
210 }
211 impl<'l, 'r, R: Round, const B: Word> $Op<&'r $target> for &'l CachedFBig<R, B> {
212 type Output = CachedFBig<R, B>;
213 #[inline]
214 fn $op(self, rhs: &$target) -> Self::Output {
215 self.$op(FBig::<R, B>::from(rhs.clone()))
216 }
217 }
218 };
219}
220
221macro_rules! impl_cached_binop_reverse_with_primitive {
222 ($Op:ident, $op:ident, $target:ty) => {
223 impl<R: Round, const B: Word> $Op<CachedFBig<R, B>> for $target {
224 type Output = CachedFBig<R, B>;
225 #[inline]
226 fn $op(self, rhs: CachedFBig<R, B>) -> Self::Output {
227 FBig::<R, B>::from(self).$op(rhs)
228 }
229 }
230 impl<'l, R: Round, const B: Word> $Op<CachedFBig<R, B>> for &'l $target {
231 type Output = CachedFBig<R, B>;
232 #[inline]
233 fn $op(self, rhs: CachedFBig<R, B>) -> Self::Output {
234 FBig::<R, B>::from(self.clone()).$op(rhs)
235 }
236 }
237 impl<'r, R: Round, const B: Word> $Op<&'r CachedFBig<R, B>> for $target {
238 type Output = CachedFBig<R, B>;
239 #[inline]
240 fn $op(self, rhs: &CachedFBig<R, B>) -> Self::Output {
241 FBig::<R, B>::from(self).$op(rhs)
242 }
243 }
244 impl<'l, 'r, R: Round, const B: Word> $Op<&'r CachedFBig<R, B>> for &'l $target {
245 type Output = CachedFBig<R, B>;
246 #[inline]
247 fn $op(self, rhs: &CachedFBig<R, B>) -> Self::Output {
248 FBig::<R, B>::from(self.clone()).$op(rhs)
249 }
250 }
251 };
252}
253
254macro_rules! impl_cached_binop_assign_with_primitive {
255 ($OpAssign:ident, $op_assign:ident, $Op:ident, $op:ident, $target:ty) => {
256 impl<R: Round, const B: Word> $OpAssign<$target> for CachedFBig<R, B> {
257 #[inline]
258 fn $op_assign(&mut self, rhs: $target) {
259 self.$op_assign(FBig::<R, B>::from(rhs));
260 }
261 }
262 impl<R: Round, const B: Word> $OpAssign<&$target> for CachedFBig<R, B> {
263 #[inline]
264 fn $op_assign(&mut self, rhs: &$target) {
265 self.$op_assign(FBig::<R, B>::from(rhs.clone()));
266 }
267 }
268 };
269}
270
271macro_rules! impl_cached_binop_with_primitives {
272 ($Op:ident, $op:ident $(, $t:ty)*) => {
273 $(
274 impl_cached_binop_one_way_with_primitive!($Op, $op, $t);
275 impl_cached_binop_reverse_with_primitive!($Op, $op, $t);
276 )*
277 };
278}
279
280macro_rules! impl_cached_binop_assign_with_primitives {
281 ($OpAssign:ident, $op_assign:ident, $Op:ident, $op:ident $(, $t:ty)*) => {
282 $(
283 impl_cached_binop_assign_with_primitive!($OpAssign, $op_assign, $Op, $op, $t);
284 )*
285 };
286}
287
288impl_cached_binop_with_primitives!(Add, add, u8, u16, u32, u64, u128, usize, dashu_int::UBig);
290impl_cached_binop_with_primitives!(Sub, sub, u8, u16, u32, u64, u128, usize, dashu_int::UBig);
291impl_cached_binop_with_primitives!(Mul, mul, u8, u16, u32, u64, u128, usize, dashu_int::UBig);
292impl_cached_binop_with_primitives!(Div, div, u8, u16, u32, u64, u128, usize, dashu_int::UBig);
293impl_cached_binop_with_primitives!(Rem, rem, u8, u16, u32, u64, u128, usize, dashu_int::UBig);
294
295impl_cached_binop_with_primitives!(Add, add, i8, i16, i32, i64, i128, isize, dashu_int::IBig);
297impl_cached_binop_with_primitives!(Sub, sub, i8, i16, i32, i64, i128, isize, dashu_int::IBig);
298impl_cached_binop_with_primitives!(Mul, mul, i8, i16, i32, i64, i128, isize, dashu_int::IBig);
299impl_cached_binop_with_primitives!(Div, div, i8, i16, i32, i64, i128, isize, dashu_int::IBig);
300impl_cached_binop_with_primitives!(Rem, rem, i8, i16, i32, i64, i128, isize, dashu_int::IBig);
301
302#[rustfmt::skip]
304impl_cached_binop_assign_with_primitives!(AddAssign, add_assign, Add, add,
305 u8, u16, u32, u64, u128, usize, dashu_int::UBig,
306 i8, i16, i32, i64, i128, isize, dashu_int::IBig);
307#[rustfmt::skip]
308impl_cached_binop_assign_with_primitives!(SubAssign, sub_assign, Sub, sub,
309 u8, u16, u32, u64, u128, usize, dashu_int::UBig,
310 i8, i16, i32, i64, i128, isize, dashu_int::IBig);
311#[rustfmt::skip]
312impl_cached_binop_assign_with_primitives!(MulAssign, mul_assign, Mul, mul,
313 u8, u16, u32, u64, u128, usize, dashu_int::UBig,
314 i8, i16, i32, i64, i128, isize, dashu_int::IBig);
315#[rustfmt::skip]
316impl_cached_binop_assign_with_primitives!(DivAssign, div_assign, Div, div,
317 u8, u16, u32, u64, u128, usize, dashu_int::UBig,
318 i8, i16, i32, i64, i128, isize, dashu_int::IBig);
319#[rustfmt::skip]
320impl_cached_binop_assign_with_primitives!(RemAssign, rem_assign, Rem, rem,
321 u8, u16, u32, u64, u128, usize, dashu_int::UBig,
322 i8, i16, i32, i64, i128, isize, dashu_int::IBig);
323
324impl<R: Round, const B: Word> Neg for CachedFBig<R, B> {
329 type Output = CachedFBig<R, B>;
330 #[inline]
331 fn neg(self) -> Self::Output {
332 CachedFBig::from_fbig(-self.fbig, &self.cache)
333 }
334}
335
336impl<R: Round, const B: Word> Neg for &CachedFBig<R, B> {
337 type Output = CachedFBig<R, B>;
338 #[inline]
339 fn neg(self) -> Self::Output {
340 CachedFBig::from_fbig(-&self.fbig, &self.cache)
341 }
342}
343
344impl<R: Round, const B: Word> Abs for CachedFBig<R, B> {
345 type Output = CachedFBig<R, B>;
346 #[inline]
347 fn abs(self) -> Self::Output {
348 CachedFBig::from_fbig(Abs::abs(self.fbig), &self.cache)
349 }
350}
351
352impl<R: Round, const B: Word> Shl<isize> for CachedFBig<R, B> {
357 type Output = Self;
358 #[inline]
359 fn shl(self, rhs: isize) -> Self::Output {
360 CachedFBig::from_fbig(self.fbig << rhs, &self.cache)
361 }
362}
363
364impl<R: Round, const B: Word> ShlAssign<isize> for CachedFBig<R, B> {
365 #[inline]
366 fn shl_assign(&mut self, rhs: isize) {
367 self.fbig <<= rhs;
368 }
369}
370
371impl<R: Round, const B: Word> Shr<isize> for CachedFBig<R, B> {
372 type Output = Self;
373 #[inline]
374 fn shr(self, rhs: isize) -> Self::Output {
375 CachedFBig::from_fbig(self.fbig >> rhs, &self.cache)
376 }
377}
378
379impl<R: Round, const B: Word> ShrAssign<isize> for CachedFBig<R, B> {
380 #[inline]
381 fn shr_assign(&mut self, rhs: isize) {
382 self.fbig >>= rhs;
383 }
384}
385
386impl<R: Round, const B: Word> Mul<Sign> for CachedFBig<R, B> {
391 type Output = Self;
392 #[inline]
393 fn mul(self, rhs: Sign) -> Self::Output {
394 CachedFBig::from_fbig(self.fbig * rhs, &self.cache)
395 }
396}
397
398impl<R: Round, const B: Word> Mul<CachedFBig<R, B>> for Sign {
399 type Output = CachedFBig<R, B>;
400 #[inline]
401 fn mul(self, rhs: CachedFBig<R, B>) -> Self::Output {
402 CachedFBig::from_fbig(self * rhs.fbig, &rhs.cache)
403 }
404}
405
406impl<R: Round, const B: Word> MulAssign<Sign> for CachedFBig<R, B> {
407 #[inline]
408 fn mul_assign(&mut self, rhs: Sign) {
409 self.fbig *= rhs;
410 }
411}
412
413impl<R: Round, const B: Word> SquareRoot for CachedFBig<R, B> {
418 type Output = Self;
419 #[inline]
420 fn sqrt(&self) -> Self::Output {
421 CachedFBig::from_fbig(SquareRoot::sqrt(&self.fbig), &self.cache)
422 }
423}
424
425impl<R: Round, const B: Word> CubicRoot for CachedFBig<R, B> {
426 type Output = Self;
427 #[inline]
428 fn cbrt(&self) -> Self::Output {
429 CachedFBig::from_fbig(CubicRoot::cbrt(&self.fbig), &self.cache)
430 }
431}
432
433impl<R: Round, const B: Word> DivEuclid<CachedFBig<R, B>> for CachedFBig<R, B> {
435 type Output = dashu_int::IBig;
436 #[inline]
437 fn div_euclid(self, rhs: CachedFBig<R, B>) -> Self::Output {
438 DivEuclid::div_euclid(self.fbig, rhs.fbig)
439 }
440}
441impl<'r, R: Round, const B: Word> DivEuclid<&'r CachedFBig<R, B>> for CachedFBig<R, B> {
442 type Output = dashu_int::IBig;
443 #[inline]
444 fn div_euclid(self, rhs: &'r CachedFBig<R, B>) -> Self::Output {
445 DivEuclid::div_euclid(self.fbig, rhs.fbig.clone())
446 }
447}
448impl<R: Round, const B: Word> DivEuclid<CachedFBig<R, B>> for &CachedFBig<R, B> {
449 type Output = dashu_int::IBig;
450 #[inline]
451 fn div_euclid(self, rhs: CachedFBig<R, B>) -> Self::Output {
452 DivEuclid::div_euclid(self.fbig.clone(), rhs.fbig)
453 }
454}
455impl<'r, R: Round, const B: Word> DivEuclid<&'r CachedFBig<R, B>> for &CachedFBig<R, B> {
456 type Output = dashu_int::IBig;
457 #[inline]
458 fn div_euclid(self, rhs: &'r CachedFBig<R, B>) -> Self::Output {
459 DivEuclid::div_euclid(self.fbig.clone(), rhs.fbig.clone())
460 }
461}
462
463impl<R: Round, const B: Word> RemEuclid<CachedFBig<R, B>> for CachedFBig<R, B> {
465 type Output = CachedFBig<R, B>;
466 #[inline]
467 fn rem_euclid(self, rhs: CachedFBig<R, B>) -> Self::Output {
468 CachedFBig::from_fbig(RemEuclid::rem_euclid(self.fbig, rhs.fbig), &self.cache)
469 }
470}
471impl<'r, R: Round, const B: Word> RemEuclid<&'r CachedFBig<R, B>> for CachedFBig<R, B> {
472 type Output = CachedFBig<R, B>;
473 #[inline]
474 fn rem_euclid(self, rhs: &'r CachedFBig<R, B>) -> Self::Output {
475 CachedFBig::from_fbig(RemEuclid::rem_euclid(self.fbig, rhs.fbig.clone()), &self.cache)
476 }
477}
478impl<R: Round, const B: Word> RemEuclid<CachedFBig<R, B>> for &CachedFBig<R, B> {
479 type Output = CachedFBig<R, B>;
480 #[inline]
481 fn rem_euclid(self, rhs: CachedFBig<R, B>) -> Self::Output {
482 CachedFBig::from_fbig(RemEuclid::rem_euclid(self.fbig.clone(), rhs.fbig), &self.cache)
483 }
484}
485impl<'r, R: Round, const B: Word> RemEuclid<&'r CachedFBig<R, B>> for &CachedFBig<R, B> {
486 type Output = CachedFBig<R, B>;
487 #[inline]
488 fn rem_euclid(self, rhs: &'r CachedFBig<R, B>) -> Self::Output {
489 CachedFBig::from_fbig(
490 RemEuclid::rem_euclid(self.fbig.clone(), rhs.fbig.clone()),
491 &self.cache,
492 )
493 }
494}
495
496impl<R: Round, const B: Word> DivRemEuclid<CachedFBig<R, B>> for CachedFBig<R, B> {
498 type OutputDiv = dashu_int::IBig;
499 type OutputRem = CachedFBig<R, B>;
500 #[inline]
501 fn div_rem_euclid(self, rhs: CachedFBig<R, B>) -> (Self::OutputDiv, Self::OutputRem) {
502 let (q, r) = DivRemEuclid::div_rem_euclid(self.fbig, rhs.fbig);
503 (q, CachedFBig::from_fbig(r, &self.cache))
504 }
505}
506impl<'r, R: Round, const B: Word> DivRemEuclid<&'r CachedFBig<R, B>> for CachedFBig<R, B> {
507 type OutputDiv = dashu_int::IBig;
508 type OutputRem = CachedFBig<R, B>;
509 #[inline]
510 fn div_rem_euclid(self, rhs: &'r CachedFBig<R, B>) -> (Self::OutputDiv, Self::OutputRem) {
511 let (q, r) = DivRemEuclid::div_rem_euclid(self.fbig, rhs.fbig.clone());
512 (q, CachedFBig::from_fbig(r, &self.cache))
513 }
514}
515impl<R: Round, const B: Word> DivRemEuclid<CachedFBig<R, B>> for &CachedFBig<R, B> {
516 type OutputDiv = dashu_int::IBig;
517 type OutputRem = CachedFBig<R, B>;
518 #[inline]
519 fn div_rem_euclid(self, rhs: CachedFBig<R, B>) -> (Self::OutputDiv, Self::OutputRem) {
520 let (q, r) = DivRemEuclid::div_rem_euclid(self.fbig.clone(), rhs.fbig);
521 (q, CachedFBig::from_fbig(r, &self.cache))
522 }
523}
524impl<'r, R: Round, const B: Word> DivRemEuclid<&'r CachedFBig<R, B>> for &CachedFBig<R, B> {
525 type OutputDiv = dashu_int::IBig;
526 type OutputRem = CachedFBig<R, B>;
527 #[inline]
528 fn div_rem_euclid(self, rhs: &'r CachedFBig<R, B>) -> (Self::OutputDiv, Self::OutputRem) {
529 let (q, r) = DivRemEuclid::div_rem_euclid(self.fbig.clone(), rhs.fbig.clone());
530 (q, CachedFBig::from_fbig(r, &self.cache))
531 }
532}
533
534impl<R: Round, const B: Word> Inverse for CachedFBig<R, B> {
535 type Output = Self;
536 #[inline]
537 fn inv(self) -> Self::Output {
538 CachedFBig::from_fbig(Inverse::inv(self.fbig), &self.cache)
539 }
540}
541
542impl<R: Round, const B: Word> Sum for CachedFBig<R, B> {
551 fn sum<I: Iterator<Item = Self>>(mut iter: I) -> Self {
552 match iter.next() {
553 Some(first) => {
554 let cache = Rc::clone(&first.cache);
555 let fbig: FBig<R, B> = core::iter::once(first.fbig)
556 .chain(iter.map(|c| c.fbig))
557 .sum();
558 CachedFBig::from_fbig(fbig, &cache)
559 }
560 None => Self::default(),
561 }
562 }
563}
564
565impl<'a, R: Round, const B: Word> Sum<&'a CachedFBig<R, B>> for CachedFBig<R, B> {
566 fn sum<I: Iterator<Item = &'a CachedFBig<R, B>>>(mut iter: I) -> Self {
567 match iter.next() {
568 Some(first) => {
569 let cache = Rc::clone(&first.cache);
570 let fbig: FBig<R, B> = core::iter::once(first.fbig.clone())
571 .chain(iter.map(|c| c.fbig.clone()))
572 .sum();
573 CachedFBig::from_fbig(fbig, &cache)
574 }
575 None => Self::default(),
576 }
577 }
578}
579
580impl<R: Round, const B: Word> Product for CachedFBig<R, B> {
581 fn product<I: Iterator<Item = Self>>(mut iter: I) -> Self {
582 match iter.next() {
583 Some(first) => {
584 let cache = Rc::clone(&first.cache);
585 let fbig: FBig<R, B> = core::iter::once(first.fbig)
586 .chain(iter.map(|c| c.fbig))
587 .product();
588 CachedFBig::from_fbig(fbig, &cache)
589 }
590 None => Self::default(),
591 }
592 }
593}
594
595impl<'a, R: Round, const B: Word> Product<&'a CachedFBig<R, B>> for CachedFBig<R, B> {
596 fn product<I: Iterator<Item = &'a CachedFBig<R, B>>>(mut iter: I) -> Self {
597 match iter.next() {
598 Some(first) => {
599 let cache = Rc::clone(&first.cache);
600 let fbig: FBig<R, B> = core::iter::once(first.fbig.clone())
601 .chain(iter.map(|c| c.fbig.clone()))
602 .product();
603 CachedFBig::from_fbig(fbig, &cache)
604 }
605 None => Self::default(),
606 }
607 }
608}
609
610macro_rules! forward_to_context {
617 ($name:ident) => {
618 #[doc = concat!("See [`FBig::", stringify!($name), "`].")]
619 #[inline]
620 pub fn $name(&self) -> CachedFBig<R, B> {
621 let mut c = self.cache.borrow_mut();
622 let fbig = self
623 .fbig
624 .context
625 .unwrap_fp(self.fbig.context.$name::<B>(&self.fbig.repr, Some(&mut *c)));
626 CachedFBig::from_fbig(fbig, &self.cache)
627 }
628 };
629}
630
631macro_rules! forward_to_context_unwrap {
634 ($name:ident) => {
635 #[doc = concat!("See [`FBig::", stringify!($name), "`].")]
636 #[inline]
637 pub fn $name(&self) -> CachedFBig<R, B> {
638 let mut c = self.cache.borrow_mut();
639 let fbig = self
640 .fbig
641 .context
642 .unwrap_fp(self.fbig.context.$name::<B>(&self.fbig.repr, Some(&mut *c)));
643 CachedFBig::from_fbig(fbig, &self.cache)
644 }
645 };
646}
647
648macro_rules! forward_to_fbig {
650 ($name:ident) => {
651 #[doc = concat!("See [`FBig::", stringify!($name), "`].")]
652 #[inline]
653 pub fn $name(&self) -> CachedFBig<R, B> {
654 CachedFBig::from_fbig(self.fbig.clone().$name(), &self.cache)
655 }
656 };
657 ($name:ident($arg:ident: $arg_ty:ty)) => {
658 #[doc = concat!("See [`FBig::", stringify!($name), "`].")]
659 #[inline]
660 pub fn $name(&self, $arg: $arg_ty) -> CachedFBig<R, B> {
661 CachedFBig::from_fbig(self.fbig.clone().$name($arg), &self.cache)
662 }
663 };
664}
665
666impl<R: Round, const B: Word> CachedFBig<R, B> {
667 forward_to_context!(ln);
668 forward_to_context!(ln_1p);
669 forward_to_context!(exp);
670 forward_to_context!(exp_m1);
671
672 forward_to_fbig!(sqrt);
673 forward_to_fbig!(inv);
674
675 forward_to_context_unwrap!(sin);
676 forward_to_context_unwrap!(cos);
677 forward_to_context_unwrap!(tan);
678 forward_to_context_unwrap!(asin);
679 forward_to_context_unwrap!(acos);
680 forward_to_context_unwrap!(atan);
681
682 forward_to_context!(sinh);
683 forward_to_context!(cosh);
684 forward_to_context!(tanh);
685 forward_to_context!(asinh);
686 forward_to_context!(acosh);
687 forward_to_context!(atanh);
688
689 forward_to_fbig!(powi(exp: dashu_int::IBig));
690 forward_to_fbig!(sqr);
691 forward_to_fbig!(cubic);
692
693 pub fn powf(&self, exp: &Self) -> Self {
695 let context = Context::max(self.fbig.context, exp.fbig.context);
696 let mut c = self.cache.borrow_mut();
697 let fbig =
698 context.unwrap_fp(context.powf::<B>(&self.fbig.repr, &exp.fbig.repr, Some(&mut *c)));
699 Self::from_fbig(fbig, &self.cache)
700 }
701
702 pub fn sin_cos(&self) -> (Self, Self) {
704 let mut guard = self.cache.borrow_mut();
705 let cache = Some(&mut *guard);
706 let (s, c) = self.fbig.context.sin_cos::<B>(&self.fbig.repr, cache);
707 (
708 Self::from_fbig(self.fbig.context.unwrap_fp(s), &self.cache),
709 Self::from_fbig(self.fbig.context.unwrap_fp(c), &self.cache),
710 )
711 }
712
713 pub fn sinh_cosh(&self) -> (Self, Self) {
715 let mut guard = self.cache.borrow_mut();
716 let cache = Some(&mut *guard);
717 let (s, c) = self.fbig.context.sinh_cosh::<B>(&self.fbig.repr, cache);
718 (
719 Self::from_fbig(self.fbig.context.unwrap_fp(s), &self.cache),
720 Self::from_fbig(self.fbig.context.unwrap_fp(c), &self.cache),
721 )
722 }
723
724 pub fn atan2(&self, x: &Self) -> Self {
726 let mut c = self.cache.borrow_mut();
727 let fbig = self.fbig.context.unwrap_fp(self.fbig.context.atan2::<B>(
728 &self.fbig.repr,
729 &x.fbig.repr,
730 Some(&mut *c),
731 ));
732 Self::from_fbig(fbig, &self.cache)
733 }
734}