1#![deny(rustdoc::broken_intra_doc_links)]
2
3use crate::{
49 core::{errors::ErrorsValidationRawReal, traits::raw::RawScalarValidate},
50 functions::FunctionErrors,
51 kernels::{RawComplexTrait, RawRealTrait},
52};
53use duplicate::duplicate_item;
54use num::Complex;
55use num_traits::Float;
56use std::backtrace::Backtrace;
57use thiserror::Error;
58
59#[cfg(debug_assertions)]
60use crate::core::{errors::capture_backtrace, traits::validation::sealed::NativeReal};
61
62#[cfg(not(debug_assertions))]
63use crate::core::traits::validation::sealed::NativeReal;
64
65#[cfg(debug_assertions)]
66use num::Zero;
67
68#[derive(Debug, Error)]
88pub enum LogarithmRealInputErrors<RawReal: RawRealTrait> {
89 #[error("negative argument ({value})!")]
94 NegativeArgument {
95 value: RawReal,
97
98 backtrace: Backtrace,
100 },
101
102 #[error("zero argument!")]
107 ZeroArgument {
108 backtrace: Backtrace,
110 },
111
112 #[error("the argument is invalid!")]
117 InvalidArgument {
118 #[source]
120 #[backtrace]
121 source: <RawReal as RawScalarValidate>::ValidationError,
122 },
123}
124
125#[derive(Debug, Error)]
142pub enum LogarithmComplexInputErrors<RawComplex: RawComplexTrait> {
143 #[error("the argument is zero!")]
148 ZeroArgument {
149 backtrace: Backtrace,
151 },
152
153 #[error("the argument is invalid!")]
158 InvalidArgument {
159 #[source]
161 #[backtrace]
162 source: <RawComplex as RawScalarValidate>::ValidationError,
163 },
164}
165
166pub type LogarithmRealErrors<RawReal> = FunctionErrors<
183 LogarithmRealInputErrors<RawReal>,
184 <RawReal as RawScalarValidate>::ValidationError,
185>;
186
187pub type LogarithmComplexErrors<RawComplex> = FunctionErrors<
204 LogarithmComplexInputErrors<RawComplex>,
205 <RawComplex as RawScalarValidate>::ValidationError,
206>;
207
208#[duplicate_item(
209 trait_name try_func func trait_doc try_func_doc func_doc err_doc;
210 [Ln] [try_ln] [ln] ["Trait for computing the [*natural logarithm*](https://en.wikipedia.org/wiki/Natural_logarithm) (base `e`) of a number.\n\nProvides both a fallible method that returns a [`Result`] and a panicking method that directly returns the computed value or panics on invalid input.\n\n# Associated Types\n\n- `Error`: The error type that is returned by the `try_ln` method. This type must implement the [`std::error::Error`] trait.\n\n# Required Methods\n\n- `try_ln`: Computes the *natural logarithm* of `self` and returns a [`Result`]. If the computation is successful, it returns [`Ok`] with the computed value. If an error occurs, it returns [`Err`] with the associated error.\n- `ln`: Computes the *natural logarithm* of `self` and directly returns the computed value. This method may panic (in Debug mode) if the computation fails."] ["Computes the *natural logarithm* of `self` and returns a [`Result`].\n\nIf the computation is successful, it returns [`Ok`] with the computed value. If an error occurs, it returns [`Err`] with the associated error.\n\n# Errors\n\nThis method returns an error if the computation fails. The error type is defined by the associated [`Ln::Error`] type."] ["Computes the *natural logarithm* of `self` and directly returns the computed value.\n\nThis method may panic (in Debug mode) if the computation fails.\n\n# Panics\n\nThis method may panic (in Debug mode) if the computation fails. It is recommended to use the `try_ln` method for safe computations."] ["The error type that is returned by the `try_ln` method."];
211 [Log10] [try_log10] [log10] ["Trait for computing the [*base-10 logarithm*](https://en.wikipedia.org/wiki/Common_logarithm) of a number.\n\nProvides both a fallible method that returns a [`Result`] and a panicking method that directly returns the computed value or panics on invalid input.\n\n# Associated Types\n\n- `Error`: The error type that is returned by the `try_log10` method. This type must implement the [`std::error::Error`] trait.\n\n# Required Methods\n\n- `try_log10`: Computes the *base-10 logarithm* of `self` and returns a [`Result`]. If the computation is successful, it returns [`Ok`] with the computed value. If an error occurs, it returns [`Err`] with the associated error.\n- `log10`: Computes the *base-10 logarithm* of `self` and directly returns the computed value. This method may panic (in Debug mode) if the computation fails."] ["Computes the *base-10 logarithm* of `self` and returns a [`Result`].\n\nIf the computation is successful, it returns [`Ok`] with the computed value. If an error occurs, it returns [`Err`] with the associated error.\n\n# Errors\n\nThis method returns an error if the computation fails. The error type is defined by the associated [`Log10::Error`] type."] ["Computes the *base-10 logarithm* of `self` and directly returns the computed value.\n\nThis method may panic (in Debug mode) if the computation fails.\n\n# Panics\n\nThis method may panic (in Debug mode) if the computation fails. It is recommended to use the `try_log10` method for safe computations."] ["The error type that is returned by the `try_log10` method."];
212 [Log2] [try_log2] [log2] ["Trait for computing the [*base-2 logarithm*](https://en.wikipedia.org/wiki/Binary_logarithm) of a number.\n\nProvides both a fallible method that returns a [`Result`] and a panicking method that directly returns the computed value or panics on invalid input.\n\n# Associated Types\n\n- `Error`: The error type that is returned by the `try_log2` method. This type must implement the [`std::error::Error`] trait.\n\n# Required Methods\n\n- `try_log2`: Computes the *base-2 logarithm* of `self` and returns a [`Result`]. If the computation is successful, it returns [`Ok`] with the computed value. If an error occurs, it returns [`Err`] with the associated error.\n- `log2`: Computes the *base-2 logarithm* of `self` and directly returns the computed value. This method may panic (in Debug mode) if the computation fails."] ["Computes the *base-2 logarithm* of `self` and returns a [`Result`].\n\nIf the computation is successful, it returns [`Ok`] with the computed value. If an error occurs, it returns [`Err`] with the associated error.\n\n# Errors\n\nThis method returns an error if the computation fails. The error type is defined by the associated [`Log2::Error`] type."] ["Computes the *base-2 logarithm* of `self` and directly returns the computed value.\n\nThis method may panic (in Debug mode) if the computation fails.\n\n# Panics\n\nThis method may panic (in Debug mode) if the computation fails. It is recommended to use the `try_log2` method for safe computations."] ["The error type that is returned by the `try_log2` method."];
213)]
214#[doc = trait_doc]
215pub trait trait_name: Sized {
216 #[doc = err_doc]
217 type Error: std::error::Error;
218
219 #[doc = try_func_doc]
220 #[must_use = "this `Result` may contain an error that should be handled"]
221 fn try_func(self) -> Result<Self, Self::Error>;
222
223 #[doc = func_doc]
224 fn func(self) -> Self;
225}
226
227#[duplicate_item(
228 trait_name try_func func;
229 [Ln] [try_ln] [ln];
230 [Log10] [try_log10] [log10];
231 [Log2] [try_log2] [log2];
232)]
233impl<T> trait_name for T
234where
235 T: NativeReal<ValidationError = ErrorsValidationRawReal<T>>,
236{
237 type Error = LogarithmRealErrors<Self>;
238
239 #[inline(always)]
240 fn try_func(self) -> Result<Self, Self::Error> {
241 #[cfg(debug_assertions)]
242 {
243 self.validate_raw_scalar()
244 .map_err(|e| LogarithmRealInputErrors::InvalidArgument { source: e }.into())
245 .and_then(|v| {
246 let zero = T::zero();
247 if v < zero {
248 Err(LogarithmRealInputErrors::NegativeArgument {
249 value: v,
250 backtrace: capture_backtrace(),
251 }
252 .into())
253 } else if v == zero {
254 Err(LogarithmRealInputErrors::ZeroArgument {
255 backtrace: capture_backtrace(),
256 }
257 .into())
258 } else {
259 <T as Float>::func(v)
260 .validate_raw_scalar()
261 .map_err(|e| LogarithmRealErrors::Output { source: e })
262 }
263 })
264 }
265 #[cfg(not(debug_assertions))]
266 {
267 Ok(<T as Float>::func(self))
268 }
269 }
270
271 #[inline(always)]
272 fn func(self) -> Self {
273 #[cfg(debug_assertions)]
274 {
275 self.try_func().unwrap()
276 }
277 #[cfg(not(debug_assertions))]
278 {
279 <T as Float>::func(self)
280 }
281 }
282}
283
284#[duplicate_item(
285 trait_name try_func func;
286 [Ln] [try_ln] [ln];
287 [Log10] [try_log10] [log10];
288 [Log2] [try_log2] [log2];
289)]
290impl<T> trait_name for Complex<T>
291where
292 Self: RawComplexTrait<RawReal = T>,
293 T: NativeReal<ValidationError = ErrorsValidationRawReal<T>>,
294{
295 type Error = LogarithmComplexErrors<Self>;
296
297 #[inline(always)]
298 fn try_func(self) -> Result<Self, Self::Error> {
299 #[cfg(debug_assertions)]
300 {
301 self.validate_raw_scalar()
302 .map_err(|e| LogarithmComplexInputErrors::InvalidArgument { source: e }.into())
303 .and_then(|v| {
304 if Zero::is_zero(&v) {
305 Err(LogarithmComplexInputErrors::ZeroArgument {
306 backtrace: capture_backtrace(),
307 }
308 .into())
309 } else {
310 Complex::func(v)
311 .validate_raw_scalar()
312 .map_err(|e| LogarithmComplexErrors::Output { source: e })
313 }
314 })
315 }
316 #[cfg(not(debug_assertions))]
317 {
318 Ok(Complex::func(self))
319 }
320 }
321
322 #[inline(always)]
323 fn func(self) -> Self {
324 #[cfg(debug_assertions)]
325 {
326 self.try_func().unwrap()
327 }
328 #[cfg(not(debug_assertions))]
329 {
330 Complex::func(self)
331 }
332 }
333}
334pub trait LogarithmFunctions: Ln + Log2 + Log10 {}
380
381impl<T> LogarithmFunctions for T where T: Ln + Log2 + Log10 {}
382#[cfg(test)]
386mod tests {
387 use super::*;
388
389 #[cfg(feature = "rug")]
390 use crate::backends::rug::validated::{ComplexRugStrictFinite, RealRugStrictFinite};
391
392 #[cfg(feature = "rug")]
393 use try_create::TryNew;
394
395 mod ln {
396 use super::*;
397
398 mod native {
399 use super::*;
400
401 mod real {
402 use super::*;
403
404 #[test]
405 fn test_f64_ln_valid() {
406 let value = 10.0;
407 let expected_result = std::f64::consts::LN_10;
408 assert_eq!(Float::ln(value), expected_result);
409 assert_eq!(Ln::ln(value), expected_result);
410 assert_eq!(value.try_ln().unwrap(), expected_result);
411 }
412
413 #[test]
414 #[cfg(debug_assertions)]
415 fn test_f64_ln_zero() {
416 let value = 0.0;
417 let result = value.try_ln();
418 assert!(matches!(
419 result,
420 Err(LogarithmRealErrors::Input(
421 LogarithmRealInputErrors::ZeroArgument { .. }
422 ))
423 ));
424 }
425
426 #[test]
427 #[cfg(debug_assertions)]
428 fn test_f64_ln_negative() {
429 let value = -10.0;
430 let result = value.try_ln();
431 assert!(matches!(
432 result,
433 Err(LogarithmRealErrors::Input(
434 LogarithmRealInputErrors::NegativeArgument { .. }
435 ))
436 ));
437 }
438
439 #[test]
440 fn test_f64_ln_one() {
441 let value = 1.0;
442 let expected_result = 0.0;
443 assert_eq!(Float::ln(value), expected_result);
444 assert_eq!(Ln::ln(value), expected_result);
445 assert_eq!(value.try_ln().unwrap(), expected_result);
446 }
447
448 #[test]
449 #[cfg(debug_assertions)]
450 fn test_f64_ln_infinity() {
451 let value = f64::INFINITY;
452 let result = value.try_ln();
453 assert!(matches!(
454 result,
455 Err(LogarithmRealErrors::Input(
456 LogarithmRealInputErrors::InvalidArgument { .. }
457 ))
458 ));
459 }
460
461 #[test]
462 #[cfg(debug_assertions)]
463 fn test_f64_ln_nan() {
464 let value = f64::NAN;
465 let result = value.try_ln();
466 assert!(matches!(
467 result,
468 Err(LogarithmRealErrors::Input(
469 LogarithmRealInputErrors::InvalidArgument { .. }
470 ))
471 ));
472 }
473 }
474
475 mod complex {
476 use super::*;
477
478 #[test]
479 fn test_complex_f64_ln_valid() {
480 let value = Complex::new(10.0, 0.0);
481 let expected_result = Complex::new(std::f64::consts::LN_10, 0.0);
482 assert_eq!(value.ln(), expected_result);
483 assert_eq!(value.try_ln().unwrap(), expected_result);
484 }
485
486 #[test]
487 #[cfg(debug_assertions)]
488 fn test_complex_f64_ln_zero() {
489 let value = Complex::new(0.0, 0.0);
490 let result = value.try_ln();
491 assert!(matches!(
492 result,
493 Err(LogarithmComplexErrors::Input(
494 LogarithmComplexInputErrors::ZeroArgument { .. }
495 ))
496 ));
497 }
498
499 #[test]
500 fn test_complex_f64_ln_negative() {
501 let value = Complex::new(-10.0, 0.0);
502 let expected_result =
503 Complex::new(std::f64::consts::LN_10, std::f64::consts::PI);
504 assert_eq!(value.ln(), expected_result);
505 assert_eq!(value.try_ln().unwrap(), expected_result);
506 }
507
508 #[test]
509 fn test_complex_f64_ln_one() {
510 let value = Complex::new(1.0, 0.0);
511 let expected_result = Complex::new(0.0, 0.0);
512 assert_eq!(value.ln(), expected_result);
513 assert_eq!(value.try_ln().unwrap(), expected_result);
514 }
515
516 #[test]
517 #[cfg(debug_assertions)]
518 fn test_complex_f64_ln_infinity() {
519 let value = Complex::new(f64::INFINITY, 0.0);
520 let result = value.try_ln();
521 assert!(matches!(
522 result,
523 Err(LogarithmComplexErrors::Input(
524 LogarithmComplexInputErrors::InvalidArgument { .. }
525 ))
526 ));
527
528 let value = Complex::new(0.0, f64::INFINITY);
529 let result = value.try_ln();
530 assert!(matches!(
531 result,
532 Err(LogarithmComplexErrors::Input(
533 LogarithmComplexInputErrors::InvalidArgument { .. }
534 ))
535 ));
536 }
537
538 #[test]
539 #[cfg(debug_assertions)]
540 fn test_complex_f64_ln_nan() {
541 let value = Complex::new(f64::NAN, 0.0);
542 let result = value.try_ln();
543 assert!(matches!(
544 result,
545 Err(LogarithmComplexErrors::Input(
546 LogarithmComplexInputErrors::InvalidArgument { .. }
547 ))
548 ));
549
550 let value = Complex::new(0.0, f64::NAN);
551 let result = value.try_ln();
552 assert!(matches!(
553 result,
554 Err(LogarithmComplexErrors::Input(
555 LogarithmComplexInputErrors::InvalidArgument { .. }
556 ))
557 ));
558 }
559 }
560 }
561
562 #[cfg(feature = "rug")]
563 mod rug53 {
564 use super::*;
565 use rug::{Complex, Float};
566
567 mod real {
568 use super::*;
569
570 #[test]
571 fn test_real_ln_valid() {
572 let value =
573 RealRugStrictFinite::<53>::try_new(Float::with_val(53, 10.0)).unwrap();
574 let expected_result = RealRugStrictFinite::<53>::try_new(Float::with_val(
575 53,
576 std::f64::consts::LN_10,
577 ))
578 .unwrap();
579 assert_eq!(value.clone().ln(), expected_result);
580 assert_eq!(value.try_ln().unwrap(), expected_result);
581 }
582
583 #[test]
584 fn test_real_ln_zero() {
585 let value =
586 RealRugStrictFinite::<53>::try_new(Float::with_val(53, 0.0)).unwrap();
587 let result = value.try_ln();
588 assert!(matches!(
589 result,
590 Err(LogarithmRealErrors::Input(
591 LogarithmRealInputErrors::ZeroArgument { .. }
592 ))
593 ));
594 }
595
596 #[test]
597 fn test_real_ln_negative() {
598 let value =
599 RealRugStrictFinite::<53>::try_new(Float::with_val(53, -10.0)).unwrap();
600 let result = value.try_ln();
601 assert!(matches!(
602 result,
603 Err(LogarithmRealErrors::Input(
604 LogarithmRealInputErrors::NegativeArgument { .. }
605 ))
606 ));
607 }
608
609 #[test]
610 fn test_real_ln_one() {
611 let value =
612 RealRugStrictFinite::<53>::try_new(Float::with_val(53, 1.0)).unwrap();
613 let expected_result =
614 RealRugStrictFinite::<53>::try_new(Float::with_val(53, 0.0)).unwrap();
615 assert_eq!(value.clone().ln(), expected_result);
616 assert_eq!(value.try_ln().unwrap(), expected_result);
617 }
618 }
619
620 mod complex {
621 use super::*;
622
623 #[test]
624 fn test_complex_ln_valid() {
625 let value = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
626 53,
627 (Float::with_val(53, 10.0), Float::with_val(53, 0.0)),
628 ))
629 .unwrap();
630 let expected_result = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
631 53,
632 (
633 Float::with_val(53, std::f64::consts::LN_10),
634 Float::with_val(53, 0.0),
635 ),
636 ))
637 .unwrap();
638 assert_eq!(value.clone().ln(), expected_result);
639 assert_eq!(value.try_ln().unwrap(), expected_result);
640 }
641
642 #[test]
643 fn test_complex_ln_zero() {
644 let value = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
645 53,
646 (Float::with_val(53, 0.0), Float::with_val(53, 0.0)),
647 ))
648 .unwrap();
649 let result = value.try_ln();
650 assert!(matches!(
651 result,
652 Err(LogarithmComplexErrors::Input(
653 LogarithmComplexInputErrors::ZeroArgument { .. }
654 ))
655 ));
656 }
657
658 #[test]
659 fn test_complex_ln_negative() {
660 let value = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
661 53,
662 (Float::with_val(53, -10.0), Float::with_val(53, 0.0)),
663 ))
664 .unwrap();
665 let expected_result = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
666 53,
667 (
668 Float::with_val(53, std::f64::consts::LN_10),
669 Float::with_val(53, std::f64::consts::PI),
670 ),
671 ))
672 .unwrap();
673 assert_eq!(value.clone().ln(), expected_result);
674 assert_eq!(value.try_ln().unwrap(), expected_result);
675 }
676
677 #[test]
678 fn test_complex_ln_one() {
679 let value = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
680 53,
681 (Float::with_val(53, 1.0), Float::with_val(53, 0.0)),
682 ))
683 .unwrap();
684 let expected_result = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
685 53,
686 (Float::with_val(53, 0.0), Float::with_val(53, 0.0)),
687 ))
688 .unwrap();
689 assert_eq!(value.clone().ln(), expected_result);
690 assert_eq!(value.try_ln().unwrap(), expected_result);
691 }
692 }
693 }
694 }
695
696 mod log10 {
697 use super::*;
698
699 mod native {
700 use super::*;
701
702 mod real {
703 use super::*;
704
705 #[test]
706 fn test_f64_log10_valid() {
707 let value = 10.0;
708 let expected_result = 1.0;
709 assert_eq!(Float::log10(value), expected_result);
710 assert_eq!(Log10::log10(value), expected_result);
711 assert_eq!(value.try_log10().unwrap(), expected_result);
712 }
713
714 #[test]
715 #[cfg(debug_assertions)]
716 fn test_f64_log10_zero() {
717 let value = 0.0;
718 let result = value.try_log10();
719 assert!(matches!(
720 result,
721 Err(LogarithmRealErrors::Input(
722 LogarithmRealInputErrors::ZeroArgument { .. }
723 ))
724 ));
725 }
726
727 #[test]
728 #[cfg(debug_assertions)]
729 fn test_f64_log10_negative() {
730 let value = -10.0;
731 let result = value.try_log10();
732 assert!(matches!(
733 result,
734 Err(LogarithmRealErrors::Input(
735 LogarithmRealInputErrors::NegativeArgument { .. }
736 ))
737 ));
738 }
739
740 #[test]
741 fn test_f64_log10_one() {
742 let value = 1.0;
743 let expected_result = 0.0;
744 assert_eq!(Float::log10(value), expected_result);
745 assert_eq!(Log10::log10(value), expected_result);
746 assert_eq!(value.try_log10().unwrap(), expected_result);
747 }
748
749 #[test]
750 #[cfg(debug_assertions)]
751 fn test_f64_log10_infinity() {
752 let value = f64::INFINITY;
753 let result = value.try_log10();
754 assert!(matches!(
755 result,
756 Err(LogarithmRealErrors::Input(
757 LogarithmRealInputErrors::InvalidArgument { .. }
758 ))
759 ));
760 }
761
762 #[test]
763 #[cfg(debug_assertions)]
764 fn test_f64_log10_nan() {
765 let value = f64::NAN;
766 let result = value.try_log10();
767 assert!(matches!(
768 result,
769 Err(LogarithmRealErrors::Input(
770 LogarithmRealInputErrors::InvalidArgument { .. }
771 ))
772 ));
773 }
774 }
775
776 mod complex {
777 use super::*;
778
779 #[test]
780 fn test_complex_f64_log10_valid() {
781 let value = Complex::new(10.0, 0.0);
782 let expected_result = Complex::new(1.0, 0.0);
783 assert_eq!(value.log10(), expected_result);
784 assert_eq!(value.try_log10().unwrap(), expected_result);
785 }
786
787 #[test]
788 #[cfg(debug_assertions)]
789 fn test_complex_f64_log10_zero() {
790 let value = Complex::new(0.0, 0.0);
791 let result = value.try_log10();
792 assert!(matches!(
793 result,
794 Err(LogarithmComplexErrors::Input(
795 LogarithmComplexInputErrors::ZeroArgument { .. }
796 ))
797 ));
798 }
799
800 #[test]
801 #[cfg(debug_assertions)]
802 fn test_complex_f64_log10_negative() {
803 let value = Complex::new(-10.0, 0.0);
804 let expected_result = Complex::new(1.0, 1.3643763538418412);
805 assert_eq!(value.log10(), expected_result);
806 assert_eq!(value.try_log10().unwrap(), expected_result);
807 }
808
809 #[test]
810 fn test_complex_f64_log10_one() {
811 let value = Complex::new(1.0, 0.0);
812 let expected_result = Complex::new(0.0, 0.0);
813 assert_eq!(value.log10(), expected_result);
814 assert_eq!(value.try_log10().unwrap(), expected_result);
815 }
816
817 #[test]
818 #[cfg(debug_assertions)]
819 fn test_complex_f64_log10_infinity() {
820 let value = Complex::new(f64::INFINITY, 0.0);
821 let result = value.try_log10();
822 assert!(matches!(
823 result,
824 Err(LogarithmComplexErrors::Input(
825 LogarithmComplexInputErrors::InvalidArgument { .. }
826 ))
827 ));
828
829 let value = Complex::new(0.0, f64::INFINITY);
830 let result = value.try_log10();
831 assert!(matches!(
832 result,
833 Err(LogarithmComplexErrors::Input(
834 LogarithmComplexInputErrors::InvalidArgument { .. }
835 ))
836 ));
837 }
838
839 #[test]
840 #[cfg(debug_assertions)]
841 fn test_complex_f64_log10_nan() {
842 let value = Complex::new(f64::NAN, 0.0);
843 let result = value.try_log10();
844 assert!(matches!(
845 result,
846 Err(LogarithmComplexErrors::Input(
847 LogarithmComplexInputErrors::InvalidArgument { .. }
848 ))
849 ));
850
851 let value = Complex::new(0.0, f64::NAN);
852 let result = value.try_log10();
853 assert!(matches!(
854 result,
855 Err(LogarithmComplexErrors::Input(
856 LogarithmComplexInputErrors::InvalidArgument { .. }
857 ))
858 ));
859 }
860 }
861 }
862
863 #[cfg(feature = "rug")]
864 mod rug53 {
865 use super::*;
866 use rug::{Complex, Float};
867
868 mod real {
869 use super::*;
870
871 #[test]
872 fn test_real_log10_valid() {
873 let value =
874 RealRugStrictFinite::<53>::try_new(Float::with_val(53, 10.0)).unwrap();
875 let expected_result =
876 RealRugStrictFinite::<53>::try_new(Float::with_val(53, 1.0)).unwrap();
877 assert_eq!(value.clone().log10(), expected_result);
878 assert_eq!(value.try_log10().unwrap(), expected_result);
879 }
880
881 #[test]
882 fn test_real_log10_zero() {
883 let value =
884 RealRugStrictFinite::<53>::try_new(Float::with_val(53, 0.0)).unwrap();
885 let result = value.try_log10();
886 assert!(matches!(
887 result,
888 Err(LogarithmRealErrors::Input(
889 LogarithmRealInputErrors::ZeroArgument { .. }
890 ))
891 ));
892 }
893
894 #[test]
895 fn test_real_log10_negative() {
896 let value =
897 RealRugStrictFinite::<53>::try_new(Float::with_val(53, -10.0)).unwrap();
898 let result = value.try_log10();
899 assert!(matches!(
900 result,
901 Err(LogarithmRealErrors::Input(
902 LogarithmRealInputErrors::NegativeArgument { .. }
903 ))
904 ));
905 }
906
907 #[test]
908 fn test_real_log10_one() {
909 let value =
910 RealRugStrictFinite::<53>::try_new(Float::with_val(53, 1.0)).unwrap();
911 let expected_result =
912 RealRugStrictFinite::<53>::try_new(Float::with_val(53, 0.0)).unwrap();
913 assert_eq!(value.clone().log10(), expected_result);
914 assert_eq!(value.try_log10().unwrap(), expected_result);
915 }
916 }
917
918 mod complex {
919 use super::*;
920
921 #[test]
922 fn test_complex_log10_valid() {
923 let value = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
924 53,
925 (Float::with_val(53, 10.0), Float::with_val(53, 0.0)),
926 ))
927 .unwrap();
928 let expected_result = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
929 53,
930 (Float::with_val(53, 1.0), Float::with_val(53, 0.0)),
931 ))
932 .unwrap();
933 assert_eq!(value.clone().log10(), expected_result);
934 assert_eq!(value.try_log10().unwrap(), expected_result);
935 }
936
937 #[test]
938 fn test_complex_log10_zero() {
939 let value = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
940 53,
941 (Float::with_val(53, 0.0), Float::with_val(53, 0.0)),
942 ))
943 .unwrap();
944 let result = value.try_log10();
945 assert!(matches!(
946 result,
947 Err(LogarithmComplexErrors::Input(
948 LogarithmComplexInputErrors::ZeroArgument { .. }
949 ))
950 ));
951 }
952
953 #[test]
954 fn test_complex_log10_negative() {
955 let value = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
956 53,
957 (Float::with_val(53, -10.0), Float::with_val(53, 0.0)),
958 ))
959 .unwrap();
960 let expected_result = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
961 53,
962 (
963 Float::with_val(53, 1.0),
964 Float::with_val(53, 1.3643763538418414),
965 ),
966 ))
967 .unwrap();
968 assert_eq!(value.clone().log10(), expected_result);
969 assert_eq!(value.try_log10().unwrap(), expected_result);
970 }
971
972 #[test]
973 fn test_complex_log10_one() {
974 let value = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
975 53,
976 (Float::with_val(53, 1.0), Float::with_val(53, 0.0)),
977 ))
978 .unwrap();
979 let expected_result = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
980 53,
981 (Float::with_val(53, 0.0), Float::with_val(53, 0.0)),
982 ))
983 .unwrap();
984 assert_eq!(value.clone().log10(), expected_result);
985 assert_eq!(value.try_log10().unwrap(), expected_result);
986 }
987 }
988 }
989 }
990
991 mod log2 {
992 use super::*;
993
994 mod native {
995 use super::*;
996
997 mod real {
998 use super::*;
999
1000 #[test]
1001 fn test_f64_log2_valid() {
1002 let value = 10.0;
1003 let expected_result = std::f64::consts::LOG2_10;
1004 assert_eq!(Float::log2(value), expected_result);
1005 assert_eq!(Log2::log2(value), expected_result);
1006 assert_eq!(value.try_log2().unwrap(), expected_result);
1007 }
1008
1009 #[test]
1010 #[cfg(debug_assertions)]
1011 fn test_f64_log2_zero() {
1012 let value = 0.0;
1013 let result = value.try_log2();
1014 assert!(matches!(
1015 result,
1016 Err(LogarithmRealErrors::Input(
1017 LogarithmRealInputErrors::ZeroArgument { .. }
1018 ))
1019 ));
1020 }
1021
1022 #[test]
1023 #[cfg(debug_assertions)]
1024 fn test_f64_log2_negative() {
1025 let value = -10.0;
1026 let result = value.try_log2();
1027 assert!(matches!(
1028 result,
1029 Err(LogarithmRealErrors::Input(
1030 LogarithmRealInputErrors::NegativeArgument { .. }
1031 ))
1032 ));
1033 }
1034
1035 #[test]
1036 fn test_f64_log2_one() {
1037 let value = 1.0;
1038 let expected_result = 0.0;
1039 assert_eq!(Float::log2(value), expected_result);
1040 assert_eq!(Log2::log2(value), expected_result);
1041 assert_eq!(value.try_log2().unwrap(), expected_result);
1042 }
1043
1044 #[test]
1045 #[cfg(debug_assertions)]
1046 fn test_f64_log2_infinity() {
1047 let value = f64::INFINITY;
1048 let result = value.try_log2();
1049 assert!(matches!(
1050 result,
1051 Err(LogarithmRealErrors::Input(
1052 LogarithmRealInputErrors::InvalidArgument { .. }
1053 ))
1054 ));
1055 }
1056
1057 #[test]
1058 #[cfg(debug_assertions)]
1059 fn test_f64_log2_nan() {
1060 let value = f64::NAN;
1061 let result = value.try_log2();
1062 assert!(matches!(
1063 result,
1064 Err(LogarithmRealErrors::Input(
1065 LogarithmRealInputErrors::InvalidArgument { .. }
1066 ))
1067 ));
1068 }
1069 }
1070
1071 mod complex {
1072 use super::*;
1073
1074 #[test]
1075 fn test_complex_f64_log2_valid() {
1076 let value = Complex::new(10.0, 0.0);
1077 let expected_result = Complex::new(3.3219280948873626, 0.0);
1078 assert_eq!(value.log2(), expected_result);
1079 assert_eq!(value.try_log2().unwrap(), expected_result);
1080 }
1081
1082 #[test]
1083 #[cfg(debug_assertions)]
1084 fn test_complex_f64_log2_zero() {
1085 let value = Complex::new(0.0, 0.0);
1086 let result = value.try_log2();
1087 assert!(matches!(
1088 result,
1089 Err(LogarithmComplexErrors::Input(
1090 LogarithmComplexInputErrors::ZeroArgument { .. }
1091 ))
1092 ));
1093 }
1094
1095 #[test]
1096 fn test_complex_f64_log2_negative() {
1097 let value = Complex::new(-10.0, 0.0);
1098 let expected_result = Complex::new(3.3219280948873626, 4.532360141827194);
1099 assert_eq!(value.log2(), expected_result);
1100 assert_eq!(value.try_log2().unwrap(), expected_result);
1101 }
1102
1103 #[test]
1104 fn test_complex_f64_log2_one() {
1105 let value = Complex::new(1.0, 0.0);
1106 let expected_result = Complex::new(0.0, 0.0);
1107 assert_eq!(value.log2(), expected_result);
1108 assert_eq!(value.try_log2().unwrap(), expected_result);
1109 }
1110
1111 #[test]
1112 #[cfg(debug_assertions)]
1113 fn test_complex_f64_log2_infinity() {
1114 let value = Complex::new(f64::INFINITY, 0.0);
1115 let result = value.try_log2();
1116 assert!(matches!(
1117 result,
1118 Err(LogarithmComplexErrors::Input(
1119 LogarithmComplexInputErrors::InvalidArgument { .. }
1120 ))
1121 ));
1122
1123 let value = Complex::new(0.0, f64::INFINITY);
1124 let result = value.try_log2();
1125 assert!(matches!(
1126 result,
1127 Err(LogarithmComplexErrors::Input(
1128 LogarithmComplexInputErrors::InvalidArgument { .. }
1129 ))
1130 ));
1131 }
1132
1133 #[test]
1134 #[cfg(debug_assertions)]
1135 fn test_complex_f64_log2_nan() {
1136 let value = Complex::new(f64::NAN, 0.0);
1137 let result = value.try_log2();
1138 assert!(matches!(
1139 result,
1140 Err(LogarithmComplexErrors::Input(
1141 LogarithmComplexInputErrors::InvalidArgument { .. }
1142 ))
1143 ));
1144
1145 let value = Complex::new(0.0, f64::NAN);
1146 let result = value.try_log2();
1147 assert!(matches!(
1148 result,
1149 Err(LogarithmComplexErrors::Input(
1150 LogarithmComplexInputErrors::InvalidArgument { .. }
1151 ))
1152 ));
1153 }
1154 }
1155 }
1156
1157 #[cfg(feature = "rug")]
1158 mod rug53 {
1159 use super::*;
1160 use rug::{Complex, Float};
1161
1162 mod real {
1163 use super::*;
1164
1165 #[test]
1166 fn test_real_log2_valid() {
1167 let value =
1168 RealRugStrictFinite::<53>::try_new(Float::with_val(53, 10.0)).unwrap();
1169 let expected_result = RealRugStrictFinite::<53>::try_new(Float::with_val(
1170 53,
1171 std::f64::consts::LOG2_10,
1172 ))
1173 .unwrap();
1174 assert_eq!(value.clone().log2(), expected_result);
1175 assert_eq!(value.try_log2().unwrap(), expected_result);
1176 }
1177
1178 #[test]
1179 fn test_real_log2_zero() {
1180 let value =
1181 RealRugStrictFinite::<53>::try_new(Float::with_val(53, 0.0)).unwrap();
1182 let result = value.try_log2();
1183 assert!(matches!(
1184 result,
1185 Err(LogarithmRealErrors::Input(
1186 LogarithmRealInputErrors::ZeroArgument { .. }
1187 ))
1188 ));
1189 }
1190
1191 #[test]
1192 fn test_real_log2_negative() {
1193 let value =
1194 RealRugStrictFinite::<53>::try_new(Float::with_val(53, -10.0)).unwrap();
1195 let result = value.try_log2();
1196 assert!(matches!(
1197 result,
1198 Err(LogarithmRealErrors::Input(
1199 LogarithmRealInputErrors::NegativeArgument { .. }
1200 ))
1201 ));
1202 }
1203
1204 #[test]
1205 fn test_real_log2_one() {
1206 let value =
1207 RealRugStrictFinite::<53>::try_new(Float::with_val(53, 1.0)).unwrap();
1208 let expected_result =
1209 RealRugStrictFinite::<53>::try_new(Float::with_val(53, 0.0)).unwrap();
1210 assert_eq!(value.clone().log2(), expected_result);
1211 assert_eq!(value.try_log2().unwrap(), expected_result);
1212 }
1213 }
1214
1215 mod complex {
1216 use super::*;
1217
1218 #[test]
1219 fn test_complex_log2_valid() {
1220 let value = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1221 53,
1222 (Float::with_val(53, 10.0), Float::with_val(53, 0.0)),
1223 ))
1224 .unwrap();
1225 let expected_result = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1226 53,
1227 (
1228 Float::with_val(53, 3.3219280948873626),
1229 Float::with_val(53, 0.0),
1230 ),
1231 ))
1232 .unwrap();
1233 assert_eq!(value.clone().log2(), expected_result);
1234 assert_eq!(value.try_log2().unwrap(), expected_result);
1235 }
1236
1237 #[test]
1238 fn test_complex_log2_zero() {
1239 let value = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1240 53,
1241 (Float::with_val(53, 0.0), Float::with_val(53, 0.0)),
1242 ))
1243 .unwrap();
1244 let result = value.try_log2();
1245 assert!(matches!(
1246 result,
1247 Err(LogarithmComplexErrors::Input(
1248 LogarithmComplexInputErrors::ZeroArgument { .. }
1249 ))
1250 ));
1251 }
1252
1253 #[test]
1254 fn test_complex_log2_negative() {
1255 let value = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1256 53,
1257 (Float::with_val(53, -10.0), Float::with_val(53, 0.0)),
1258 ))
1259 .unwrap();
1260 let expected_result = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1261 53,
1262 (
1263 Float::with_val(53, 3.3219280948873626),
1264 Float::with_val(53, 4.532360141827194),
1265 ),
1266 ))
1267 .unwrap();
1268 assert_eq!(value.clone().log2(), expected_result);
1269 assert_eq!(value.try_log2().unwrap(), expected_result);
1270 }
1271
1272 #[test]
1273 fn test_complex_log2_one() {
1274 let value = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1275 53,
1276 (Float::with_val(53, 1.0), Float::with_val(53, 0.0)),
1277 ))
1278 .unwrap();
1279 let expected_result = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1280 53,
1281 (Float::with_val(53, 0.0), Float::with_val(53, 0.0)),
1282 ))
1283 .unwrap();
1284 assert_eq!(value.clone().log2(), expected_result);
1285 assert_eq!(value.try_log2().unwrap(), expected_result);
1286 }
1287 }
1288 }
1289 }
1290}
1291