1#![deny(rustdoc::broken_intra_doc_links)]
2
3use crate::{
40 core::{
41 errors::{
42 ErrorsRawRealToInteger, ErrorsTryFromf64, ErrorsValidationRawComplex,
43 ErrorsValidationRawReal, capture_backtrace,
44 },
45 traits::{
46 raw::{
47 RawComplexTrait, RawRealTrait, RawScalarHyperbolic, RawScalarPow, RawScalarTrait,
48 RawScalarTrigonometric,
49 },
50 validation::{FpChecks, ValidationPolicyReal},
51 },
52 },
53 functions::{Conjugate, NegAssign, Rounding, Sign},
54};
55use duplicate::duplicate_item;
56use rug::{
57 float::Constant as MpfrConstant,
58 ops::{CompleteRound, Pow},
59};
60use std::{
61 cmp::Ordering,
62 hash::{Hash, Hasher},
63 num::FpCategory,
64 ops::Neg,
65};
66
67#[duplicate_item(
68 T;
69 [rug::Float];
70 [rug::Complex];
71)]
72impl RawScalarTrigonometric for T {
73 #[duplicate_item(
74 unchecked_method method;
75 [unchecked_sin] [sin];
76 [unchecked_asin] [asin];
77 [unchecked_cos] [cos];
78 [unchecked_acos] [acos];
79 [unchecked_tan] [tan];
80 [unchecked_atan] [atan];)]
81 #[inline(always)]
82 fn unchecked_method(self) -> Self {
83 T::method(self)
84 }
85}
86
87#[duplicate_item(
88 T;
89 [rug::Float];
90 [rug::Complex];
91)]
92impl RawScalarHyperbolic for T {
93 #[duplicate_item(
94 unchecked_method method;
95 [unchecked_sinh] [sinh];
96 [unchecked_asinh] [asinh];
97 [unchecked_cosh] [cosh];
98 [unchecked_acosh] [acosh];
99 [unchecked_tanh] [tanh];
100 [unchecked_atanh] [atanh];)]
101 #[inline(always)]
102 fn unchecked_method(self) -> Self {
103 T::method(self)
104 }
105}
106
107#[duplicate_item(
108 T;
109 [rug::Float];
110 [rug::Complex];
111)]
112impl RawScalarPow for T {
113 #[duplicate_item(
114 unchecked_method exponent_type;
115 [unchecked_pow_exponent_i8] [i8];
116 [unchecked_pow_exponent_i16] [i16];
117 [unchecked_pow_exponent_i32] [i32];
118 [unchecked_pow_exponent_i64] [i64];
119 [unchecked_pow_exponent_i128] [i128];
120 [unchecked_pow_exponent_isize] [isize];
121 [unchecked_pow_exponent_u8] [u8];
122 [unchecked_pow_exponent_u16] [u16];
123 [unchecked_pow_exponent_u32] [u32];
124 [unchecked_pow_exponent_u64] [u64];
125 [unchecked_pow_exponent_u128] [u128];
126 [unchecked_pow_exponent_usize] [usize];
127 )]
128 #[inline(always)]
129 fn unchecked_method(self, exponent: &exponent_type) -> Self {
130 T::pow(self, exponent)
131 }
132}
133
134impl RawScalarTrait for rug::Float {
135 type ValidationErrors = ErrorsValidationRawReal<rug::Float>;
136
137 fn raw_zero(precision: u32) -> Self {
138 rug::Float::with_val(precision, 0.)
139 }
140
141 fn is_zero(&self) -> bool {
142 rug::Float::is_zero(self)
143 }
144
145 fn raw_one(precision: u32) -> Self {
146 rug::Float::with_val(precision, 1.)
147 }
148
149 #[duplicate_item(
150 unchecked_method method;
151 [unchecked_reciprocal] [recip];
152 [unchecked_exp] [exp];
153 [unchecked_sqrt] [sqrt];
154 [unchecked_ln] [ln];
155 [unchecked_log2] [log2];
156 [unchecked_log10] [log10];
157 )]
158 #[inline(always)]
159 fn unchecked_method(self) -> Self {
160 rug::Float::method(self)
161 }
162
163 #[inline(always)]
167 fn unchecked_mul_add(self, b: &Self, c: &Self) -> Self {
168 rug::Float::mul_add(self, b, c)
169 }
170
171 #[inline(always)]
172 fn compute_hash<H: Hasher>(&self, state: &mut H) {
173 debug_assert!(
174 self.is_finite(),
175 "Hashing a non-finite rug::Float value (i.e., NaN or Infinity) may lead to inconsistent results."
176 );
177 self.prec().hash(state);
179
180 if self.is_zero() {
182 rug::Float::with_val(self.prec(), 0.0)
184 .to_string_radix(10, None)
185 .hash(state);
186 } else {
187 self.to_string_radix(10, None).hash(state)
190 }
191 }
192}
193
194impl RawRealTrait for rug::Float {
195 type RawComplex = rug::Complex;
196
197 #[inline(always)]
198 fn unchecked_abs(self) -> rug::Float {
199 rug::Float::abs(self)
200 }
201
202 #[inline(always)]
203 fn unchecked_atan2(self, denominator: &Self) -> Self {
204 rug::Float::atan2(self, denominator)
205 }
206
207 #[inline(always)]
208 fn unchecked_pow_exponent_real(self, exponent: &Self) -> Self {
209 rug::Float::pow(self, exponent)
210 }
211
212 #[inline(always)]
213 fn unchecked_hypot(self, other: &Self) -> Self {
214 rug::Float::hypot(self, other)
215 }
216
217 #[inline(always)]
218 fn unchecked_ln_1p(self) -> Self {
219 rug::Float::ln_1p(self)
220 }
221
222 #[inline(always)]
223 fn unchecked_exp_m1(self) -> Self {
224 rug::Float::exp_m1(self)
225 }
226
227 #[inline(always)]
230 fn unchecked_mul_add_mul_mut(&mut self, mul: &Self, add_mul1: &Self, add_mul2: &Self) {
231 self.mul_add_mul_mut(mul, add_mul1, add_mul2);
232 }
233
234 #[inline(always)]
237 fn unchecked_mul_sub_mul_mut(&mut self, mul: &Self, sub_mul1: &Self, sub_mul2: &Self) {
238 self.mul_sub_mul_mut(mul, sub_mul1, sub_mul2);
239 }
240
241 #[inline(always)]
242 fn raw_total_cmp(&self, other: &Self) -> Ordering {
243 rug::Float::total_cmp(self, other)
244 }
245
246 #[inline(always)]
248 fn raw_clamp(self, min: &Self, max: &Self) -> Self {
249 rug::Float::clamp(self, min, max)
250 }
251
252 #[inline(always)]
253 fn raw_classify(&self) -> FpCategory {
254 rug::Float::classify(self)
255 }
256
257 #[inline(always)]
258 fn raw_two(precision: u32) -> Self {
259 rug::Float::with_val(precision, 2.)
260 }
261
262 #[inline(always)]
263 fn raw_one_div_2(precision: u32) -> Self {
264 rug::Float::with_val(precision, 0.5)
265 }
266
267 #[inline(always)]
268 fn raw_pi(precision: u32) -> Self {
269 rug::Float::with_val(precision, MpfrConstant::Pi)
271 }
272
273 #[inline(always)]
274 fn raw_two_pi(precision: u32) -> Self {
275 rug::Float::with_val(precision, MpfrConstant::Pi) * 2
276 }
277
278 #[inline(always)]
279 fn raw_pi_div_2(precision: u32) -> Self {
280 rug::Float::with_val(precision, MpfrConstant::Pi) / 2
281 }
282
283 #[inline(always)]
284 fn raw_max_finite(precision: u32) -> Self {
285 let one = rug::Float::with_val(precision, 1);
291 let eps = rug::Float::with_val(precision, rug::Float::u_pow_u(2, precision)).recip();
292 let significand = one - &eps;
293
294 let max_exp = rug::float::exp_max() - 1;
296 significand * rug::Float::with_val(precision, rug::Float::u_pow_u(2, max_exp as u32))
298 }
299
300 #[inline(always)]
301 fn raw_min_finite(precision: u32) -> Self {
302 Self::raw_max_finite(precision).neg()
303 }
304
305 #[inline(always)]
306 fn raw_epsilon(precision: u32) -> Self {
307 rug::Float::u_pow_u(2, precision - 1)
308 .complete(precision)
309 .recip()
310 }
311
312 #[inline(always)]
313 fn raw_ln_2(precision: u32) -> Self {
314 rug::Float::with_val(precision, MpfrConstant::Log2)
316 }
317
318 #[inline(always)]
319 fn raw_ln_10(precision: u32) -> Self {
320 let ln2 = rug::Float::with_val(precision, MpfrConstant::Log2);
323 let log2_10 = rug::Float::with_val(precision, 10).log2();
324 ln2 * log2_10
325 }
326
327 #[inline(always)]
328 fn raw_log10_2(precision: u32) -> Self {
329 rug::Float::with_val(precision, 2.).log10()
330 }
331
332 #[inline(always)]
333 fn raw_log2_10(precision: u32) -> Self {
334 rug::Float::with_val(precision, 10.).log2()
335 }
336
337 #[inline(always)]
338 fn raw_log2_e(precision: u32) -> Self {
339 rug::Float::with_val(precision, MpfrConstant::Log2).recip()
342 }
343
344 #[inline(always)]
345 fn raw_log10_e(precision: u32) -> Self {
346 let ln2 = rug::Float::with_val(precision, MpfrConstant::Log2);
348 let log2_10 = rug::Float::with_val(precision, 10).log2();
349 (ln2 * log2_10).recip()
350 }
351
352 #[inline(always)]
353 fn raw_e(precision: u32) -> Self {
354 rug::Float::with_val(precision, 1.).exp()
355 }
356
357 #[inline(always)]
358 fn try_new_raw_real_from_f64<RealPolicy: ValidationPolicyReal<Value = Self>>(
359 value: f64,
360 ) -> Result<Self, ErrorsTryFromf64<Self>> {
361 let precision = RealPolicy::PRECISION;
362
363 const F64_PRECISION: u32 = 53;
365
366 if precision < F64_PRECISION {
368 let placeholder = rug::Float::with_val(precision, value);
370 return Err(ErrorsTryFromf64::NonRepresentableExactly {
371 value_in: value,
372 value_converted_from_f64: placeholder,
373 precision,
374 backtrace: capture_backtrace(),
375 });
376 }
377
378 let value_rug = rug::Float::with_val(precision, value);
381
382 let validated =
384 RealPolicy::validate(value_rug).map_err(|e| ErrorsTryFromf64::Output { source: e })?;
385
386 Ok(validated)
387 }
388
389 #[inline(always)]
390 fn precision(&self) -> u32 {
391 rug::Float::prec(self)
392 }
393
394 #[inline(always)]
395 fn truncate_to_usize(self) -> Result<usize, ErrorsRawRealToInteger<rug::Float, usize>> {
396 if !self.is_finite() {
397 return Err(ErrorsRawRealToInteger::NotFinite {
398 value: self,
399 backtrace: capture_backtrace(),
400 });
401 }
402
403 let truncation = self.clone().trunc();
404
405 let out_of_range = || ErrorsRawRealToInteger::OutOfRange {
406 value: self,
407 min: usize::MIN,
408 max: usize::MAX,
409 backtrace: capture_backtrace(),
410 };
411
412 let truncation_as_rug_integer = truncation.to_integer().ok_or_else(out_of_range.clone())?;
413
414 truncation_as_rug_integer
415 .to_usize()
416 .ok_or_else(out_of_range)
417 }
418}
419
420impl RawScalarTrait for rug::Complex {
421 type ValidationErrors = ErrorsValidationRawComplex<ErrorsValidationRawReal<rug::Float>>;
422
423 fn raw_zero(precision: u32) -> Self {
424 rug::Complex::with_val(precision, (0., 0.))
425 }
426
427 fn is_zero(&self) -> bool {
428 rug::Complex::is_zero(self)
429 }
430
431 fn raw_one(precision: u32) -> Self {
432 rug::Complex::with_val(precision, (1., 0.))
433 }
434
435 #[duplicate_item(
436 unchecked_method method;
437 [unchecked_reciprocal] [recip];
438 [unchecked_exp] [exp];
439 [unchecked_sqrt] [sqrt];
440 [unchecked_ln] [ln];
441 [unchecked_log10] [log10];
442 )]
443 #[inline(always)]
444 fn unchecked_method(self) -> Self {
445 rug::Complex::method(self)
446 }
447
448 #[inline(always)]
449 fn unchecked_log2(self) -> Self {
450 let ln_2 = rug::Float::with_val(self.real().prec(), 2.).ln();
451 rug::Complex::ln(self) / ln_2
452 }
453
454 #[inline(always)]
458 fn unchecked_mul_add(self, b: &Self, c: &Self) -> Self {
459 rug::Complex::mul_add(self, b, c)
460 }
461
462 fn compute_hash<H: Hasher>(&self, state: &mut H) {
463 self.raw_real_part().compute_hash(state);
464 self.raw_imag_part().compute_hash(state);
465 }
466}
467
468impl Conjugate for rug::Complex {
469 #[inline(always)]
470 fn conjugate(self) -> Self {
471 rug::Complex::conj(self)
472 }
473}
474
475impl RawComplexTrait for rug::Complex {
476 type RawReal = rug::Float;
477
478 fn new_unchecked_raw_complex(real: rug::Float, imag: rug::Float) -> Self {
479 debug_assert_eq!(
480 real.prec(),
481 imag.prec(),
482 "Different precision between real and imaginary part!"
483 );
484 rug::Complex::with_val(real.prec(), (real, imag))
485 }
486
487 fn mut_raw_real_part(&mut self) -> &mut rug::Float {
489 self.mut_real()
490 }
491
492 fn mut_raw_imag_part(&mut self) -> &mut rug::Float {
494 self.mut_imag()
495 }
496
497 #[inline(always)]
498 fn unchecked_abs(self) -> rug::Float {
499 rug::Complex::abs(self).into_real_imag().0
500 }
501
502 #[inline(always)]
503 fn raw_real_part(&self) -> &rug::Float {
504 self.real()
505 }
506
507 #[inline(always)]
508 fn raw_imag_part(&self) -> &rug::Float {
509 self.imag()
510 }
511
512 #[inline(always)]
513 fn unchecked_arg(self) -> rug::Float {
514 rug::Complex::arg(self).into_real_imag().0
515 }
516
517 #[inline(always)]
518 fn unchecked_pow_exponent_real(self, exponent: &rug::Float) -> Self {
519 rug::Complex::pow(self, exponent)
520 }
521}
522
523impl FpChecks for rug::Float {
524 fn is_finite(&self) -> bool {
525 rug::Float::is_finite(self)
526 }
527
528 fn is_infinite(&self) -> bool {
529 rug::Float::is_infinite(self)
530 }
531
532 fn is_nan(&self) -> bool {
533 rug::Float::is_nan(self)
534 }
535 fn is_normal(&self) -> bool {
536 rug::Float::is_normal(self)
537 }
538}
539
540impl FpChecks for rug::Complex {
541 #[inline(always)]
543 fn is_finite(&self) -> bool {
544 self.real().is_finite() && self.imag().is_finite()
545 }
546
547 #[inline(always)]
549 fn is_infinite(&self) -> bool {
550 !self.is_nan() && (self.real().is_infinite() || self.imag().is_infinite())
551 }
552
553 #[inline(always)]
555 fn is_nan(&self) -> bool {
556 self.real().is_nan() || self.imag().is_nan()
557 }
558
559 #[inline(always)]
561 fn is_normal(&self) -> bool {
562 self.real().is_normal() && self.imag().is_normal()
563 }
564}
565
566#[duplicate_item(
568 T;
569 [rug::Float];
570 [rug::Complex];
571)]
572impl NegAssign for T {
574 fn neg_assign(&mut self) {
576 <T as rug::ops::NegAssign>::neg_assign(self);
577 }
578}
579impl Sign for rug::Float {
582 #[inline(always)]
584 fn kernel_copysign(self, sign: &Self) -> Self {
585 self.copysign(sign)
586 }
587
588 #[inline(always)]
590 fn kernel_is_sign_negative(&self) -> bool {
591 self.is_sign_negative()
592 }
593
594 #[inline(always)]
596 fn kernel_is_sign_positive(&self) -> bool {
597 self.is_sign_positive()
598 }
599
600 #[inline(always)]
608 fn kernel_signum(self) -> Self {
609 self.signum()
610 }
611}
612
613impl Rounding for rug::Float {
614 #[inline(always)]
616 fn kernel_ceil(self) -> Self {
617 self.ceil()
618 }
619
620 #[inline(always)]
622 fn kernel_floor(self) -> Self {
623 self.floor()
624 }
625
626 #[inline(always)]
628 fn kernel_fract(self) -> Self {
629 self.fract()
630 }
631
632 #[inline(always)]
634 fn kernel_round(self) -> Self {
635 self.round()
636 }
637
638 #[inline(always)]
659 fn kernel_round_ties_even(self) -> Self {
660 self.round_even()
661 }
662
663 #[inline(always)]
680 fn kernel_trunc(self) -> Self {
681 self.trunc()
682 }
683}