1#![deny(rustdoc::broken_intra_doc_links)]
2
3use crate::{
49 functions::FunctionErrors,
50 kernels::{RawComplexTrait, RawRealTrait, RawScalarTrait},
51 validation::StrictFinitePolicy,
52};
53use duplicate::duplicate_item;
54use num::Complex;
55use num::Zero;
56use std::backtrace::Backtrace;
57use thiserror::Error;
58use try_create::ValidationPolicy;
59
60#[derive(Debug, Error)]
80pub enum LogarithmRealInputErrors<RawReal: RawRealTrait> {
81 #[error("negative argument ({value})!")]
86 NegativeArgument {
87 value: RawReal,
89
90 backtrace: Backtrace,
91 },
92
93 #[error("zero argument!")]
98 ZeroArgument { backtrace: Backtrace },
99
100 #[error("the argument is invalid!")]
105 InvalidArgument {
106 #[source]
108 #[backtrace]
109 source: <RawReal as RawScalarTrait>::ValidationErrors,
110 },
111}
112
113#[derive(Debug, Error)]
130pub enum LogarithmComplexInputErrors<RawComplex: RawComplexTrait> {
131 #[error("the argument is zero!")]
136 ZeroArgument { backtrace: Backtrace },
137
138 #[error("the argument is invalid!")]
143 InvalidArgument {
144 #[source]
146 #[backtrace]
147 source: <RawComplex as RawScalarTrait>::ValidationErrors,
148 },
149}
150
151pub type LogarithmRealErrors<RawReal> = FunctionErrors<
168 LogarithmRealInputErrors<RawReal>,
169 <RawReal as RawScalarTrait>::ValidationErrors,
170>;
171
172pub type LogarithmComplexErrors<RawComplex> = FunctionErrors<
189 LogarithmComplexInputErrors<RawComplex>,
190 <RawComplex as RawScalarTrait>::ValidationErrors,
191>;
192
193#[duplicate::duplicate_item(
194 trait_name try_func func trait_doc try_func_doc func_doc err_doc;
195 [Ln] [try_ln] [ln] ["Trait for computing the [*natural logarithm*](https://en.wikipedia.org/wiki/Natural_logarithm) (base `e`) of a number.\n\nIt includes both a safe method that returns a [`Result`] and an unsafe method that directly returns the computed value.\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."];
196 [Log10] [try_log10] [log10] ["Trait for computing the [*base-10 logarithm*](https://en.wikipedia.org/wiki/Common_logarithm) of a number.\n\nIt includes both a safe method that returns a [`Result`] and an unsafe method that directly returns the computed value.\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."];
197 [Log2] [try_log2] [log2] ["Trait for computing the [*base-2 logarithm*](https://en.wikipedia.org/wiki/Binary_logarithm) of a number.\n\nIt includes both a safe method that returns a [`Result`] and an unsafe method that directly returns the computed value.\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."];
198)]
199#[doc = trait_doc]
200pub trait trait_name: Sized {
201 #[doc = err_doc]
202 type Error: std::error::Error;
203
204 #[doc = try_func_doc]
205 fn try_func(self) -> Result<Self, Self::Error>;
206
207 #[doc = func_doc]
208 fn func(self) -> Self;
209}
210
211#[duplicate::duplicate_item(
212 trait_name try_func func;
213 [Ln] [try_ln] [ln];
214 [Log10] [try_log10] [log10];
215 [Log2] [try_log2] [log2];
216)]
217impl trait_name for f64 {
218 type Error = LogarithmRealErrors<Self>;
219
220 #[inline(always)]
221 fn try_func(self) -> Result<Self, Self::Error> {
222 StrictFinitePolicy::<Self, 53>::validate(self)
223 .map_err(|e| LogarithmRealInputErrors::InvalidArgument { source: e }.into())
224 .and_then(|v| {
225 if v < 0.0 {
226 Err(LogarithmRealInputErrors::NegativeArgument {
227 value: v,
228 backtrace: Backtrace::force_capture(),
229 }
230 .into())
231 } else if v == 0. {
232 Err(LogarithmRealInputErrors::ZeroArgument {
233 backtrace: Backtrace::force_capture(),
234 }
235 .into())
236 } else {
237 StrictFinitePolicy::<Self, 53>::validate(f64::func(v))
238 .map_err(|e| LogarithmRealErrors::Output { source: e })
239 }
240 })
241 }
242
243 #[inline(always)]
244 fn func(self) -> Self {
245 #[cfg(debug_assertions)]
246 {
247 self.try_func().unwrap()
248 }
249 #[cfg(not(debug_assertions))]
250 {
251 f64::func(self)
252 }
253 }
254}
255
256#[duplicate::duplicate_item(
257 trait_name try_func func;
258 [Ln] [try_ln] [ln];
259 [Log10] [try_log10] [log10];
260 [Log2] [try_log2] [log2];
261)]
262impl trait_name for Complex<f64> {
263 type Error = LogarithmComplexErrors<Self>;
264
265 #[inline(always)]
266 fn try_func(self) -> Result<Self, Self::Error> {
267 StrictFinitePolicy::<Self, 53>::validate(self)
268 .map_err(|e| LogarithmComplexInputErrors::InvalidArgument { source: e }.into())
269 .and_then(|v| {
270 if Zero::is_zero(&v) {
271 Err(LogarithmComplexInputErrors::ZeroArgument {
272 backtrace: Backtrace::force_capture(),
273 }
274 .into())
275 } else {
276 StrictFinitePolicy::<Self, 53>::validate(Complex::func(v))
277 .map_err(|e| LogarithmComplexErrors::Output { source: e })
278 }
279 })
280 }
281
282 #[inline(always)]
283 fn func(self) -> Self {
284 #[cfg(debug_assertions)]
285 {
286 self.try_func().unwrap()
287 }
288 #[cfg(not(debug_assertions))]
289 {
290 Complex::func(self)
291 }
292 }
293}
294pub trait LogarithmFunctions: Ln + Log2 + Log10 {}
340
341#[duplicate_item(
342 T;
343 [f64];
344 [Complex<f64>];
345)]
346impl LogarithmFunctions for T {}
347#[cfg(test)]
351mod tests {
352 use super::*;
353
354 #[cfg(feature = "rug")]
355 use crate::kernels::rug::{ComplexRugStrictFinite, RealRugStrictFinite};
356
357 #[cfg(feature = "rug")]
358 use try_create::TryNew;
359
360 mod ln {
361 use super::*;
362
363 mod native64 {
364 use super::*;
365
366 mod real {
367 use super::*;
368
369 #[test]
370 fn test_f64_ln_valid() {
371 let value = 10.0;
372 let expected_result = std::f64::consts::LN_10;
373 assert_eq!(value.ln(), expected_result);
374 assert_eq!(value.try_ln().unwrap(), expected_result);
375 }
376
377 #[test]
378 fn test_f64_ln_zero() {
379 let value = 0.0;
380 let result = value.try_ln();
381 assert!(matches!(
382 result,
383 Err(LogarithmRealErrors::Input {
384 source: LogarithmRealInputErrors::ZeroArgument { .. }
385 })
386 ));
387 }
388
389 #[test]
390 fn test_f64_ln_negative() {
391 let value = -10.0;
392 let result = value.try_ln();
393 assert!(matches!(
394 result,
395 Err(LogarithmRealErrors::Input {
396 source: LogarithmRealInputErrors::NegativeArgument { .. }
397 })
398 ));
399 }
400
401 #[test]
402 fn test_f64_ln_one() {
403 let value = 1.0;
404 let expected_result = 0.0;
405 assert_eq!(value.ln(), expected_result);
406 assert_eq!(value.try_ln().unwrap(), expected_result);
407 }
408
409 #[test]
410 fn test_f64_ln_infinity() {
411 let value = f64::INFINITY;
412 let result = value.try_ln();
413 assert!(matches!(
414 result,
415 Err(LogarithmRealErrors::Input {
416 source: LogarithmRealInputErrors::InvalidArgument { .. }
417 })
418 ));
419 }
420
421 #[test]
422 fn test_f64_ln_nan() {
423 let value = f64::NAN;
424 let result = value.try_ln();
425 assert!(matches!(
426 result,
427 Err(LogarithmRealErrors::Input {
428 source: LogarithmRealInputErrors::InvalidArgument { .. }
429 })
430 ));
431 }
432 }
433
434 mod complex {
435 use super::*;
436
437 #[test]
438 fn test_complex_f64_ln_valid() {
439 let value = Complex::new(10.0, 0.0);
440 let expected_result = Complex::new(std::f64::consts::LN_10, 0.0);
441 assert_eq!(value.ln(), expected_result);
442 assert_eq!(value.try_ln().unwrap(), expected_result);
443 }
444
445 #[test]
446 fn test_complex_f64_ln_zero() {
447 let value = Complex::new(0.0, 0.0);
448 let result = value.try_ln();
449 assert!(matches!(
450 result,
451 Err(LogarithmComplexErrors::Input {
452 source: LogarithmComplexInputErrors::ZeroArgument { .. }
453 })
454 ));
455 }
456
457 #[test]
458 fn test_complex_f64_ln_negative() {
459 let value = Complex::new(-10.0, 0.0);
460 let expected_result =
461 Complex::new(std::f64::consts::LN_10, std::f64::consts::PI);
462 assert_eq!(value.ln(), expected_result);
463 assert_eq!(value.try_ln().unwrap(), expected_result);
464 }
465
466 #[test]
467 fn test_complex_f64_ln_one() {
468 let value = Complex::new(1.0, 0.0);
469 let expected_result = Complex::new(0.0, 0.0);
470 assert_eq!(value.ln(), expected_result);
471 assert_eq!(value.try_ln().unwrap(), expected_result);
472 }
473
474 #[test]
475 fn test_complex_f64_ln_infinity() {
476 let value = Complex::new(f64::INFINITY, 0.0);
477 let result = value.try_ln();
478 assert!(matches!(
479 result,
480 Err(LogarithmComplexErrors::Input {
481 source: LogarithmComplexInputErrors::InvalidArgument { .. }
482 })
483 ));
484
485 let value = Complex::new(0.0, f64::INFINITY);
486 let result = value.try_ln();
487 assert!(matches!(
488 result,
489 Err(LogarithmComplexErrors::Input {
490 source: LogarithmComplexInputErrors::InvalidArgument { .. }
491 })
492 ));
493 }
494
495 #[test]
496 fn test_complex_f64_ln_nan() {
497 let value = Complex::new(f64::NAN, 0.0);
498 let result = value.try_ln();
499 assert!(matches!(
500 result,
501 Err(LogarithmComplexErrors::Input {
502 source: LogarithmComplexInputErrors::InvalidArgument { .. }
503 })
504 ));
505
506 let value = Complex::new(0.0, f64::NAN);
507 let result = value.try_ln();
508 assert!(matches!(
509 result,
510 Err(LogarithmComplexErrors::Input {
511 source: LogarithmComplexInputErrors::InvalidArgument { .. }
512 })
513 ));
514 }
515 }
516 }
517
518 #[cfg(feature = "rug")]
519 mod rug53 {
520 use super::*;
521 use rug::{Complex, Float};
522
523 mod real {
524 use super::*;
525
526 #[test]
527 fn test_real_ln_valid() {
528 let value =
529 RealRugStrictFinite::<53>::try_new(Float::with_val(53, 10.0)).unwrap();
530 let expected_result = RealRugStrictFinite::<53>::try_new(Float::with_val(
531 53,
532 std::f64::consts::LN_10,
533 ))
534 .unwrap();
535 assert_eq!(value.clone().ln(), expected_result);
536 assert_eq!(value.try_ln().unwrap(), expected_result);
537 }
538
539 #[test]
540 fn test_real_ln_zero() {
541 let value =
542 RealRugStrictFinite::<53>::try_new(Float::with_val(53, 0.0)).unwrap();
543 let result = value.try_ln();
544 assert!(matches!(
545 result,
546 Err(LogarithmRealErrors::Input {
547 source: LogarithmRealInputErrors::ZeroArgument { .. }
548 })
549 ));
550 }
551
552 #[test]
553 fn test_real_ln_negative() {
554 let value =
555 RealRugStrictFinite::<53>::try_new(Float::with_val(53, -10.0)).unwrap();
556 let result = value.try_ln();
557 assert!(matches!(
558 result,
559 Err(LogarithmRealErrors::Input {
560 source: LogarithmRealInputErrors::NegativeArgument { .. }
561 })
562 ));
563 }
564
565 #[test]
566 fn test_real_ln_one() {
567 let value =
568 RealRugStrictFinite::<53>::try_new(Float::with_val(53, 1.0)).unwrap();
569 let expected_result =
570 RealRugStrictFinite::<53>::try_new(Float::with_val(53, 0.0)).unwrap();
571 assert_eq!(value.clone().ln(), expected_result);
572 assert_eq!(value.try_ln().unwrap(), expected_result);
573 }
574 }
575
576 mod complex {
577 use super::*;
578
579 #[test]
580 fn test_complex_ln_valid() {
581 let value = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
582 53,
583 (Float::with_val(53, 10.0), Float::with_val(53, 0.0)),
584 ))
585 .unwrap();
586 let expected_result = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
587 53,
588 (
589 Float::with_val(53, std::f64::consts::LN_10),
590 Float::with_val(53, 0.0),
591 ),
592 ))
593 .unwrap();
594 assert_eq!(value.clone().ln(), expected_result);
595 assert_eq!(value.try_ln().unwrap(), expected_result);
596 }
597
598 #[test]
599 fn test_complex_ln_zero() {
600 let value = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
601 53,
602 (Float::with_val(53, 0.0), Float::with_val(53, 0.0)),
603 ))
604 .unwrap();
605 let result = value.try_ln();
606 assert!(matches!(
607 result,
608 Err(LogarithmComplexErrors::Input {
609 source: LogarithmComplexInputErrors::ZeroArgument { .. }
610 })
611 ));
612 }
613
614 #[test]
615 fn test_complex_ln_negative() {
616 let value = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
617 53,
618 (Float::with_val(53, -10.0), Float::with_val(53, 0.0)),
619 ))
620 .unwrap();
621 let expected_result = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
622 53,
623 (
624 Float::with_val(53, std::f64::consts::LN_10),
625 Float::with_val(53, std::f64::consts::PI),
626 ),
627 ))
628 .unwrap();
629 assert_eq!(value.clone().ln(), expected_result);
630 assert_eq!(value.try_ln().unwrap(), expected_result);
631 }
632
633 #[test]
634 fn test_complex_ln_one() {
635 let value = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
636 53,
637 (Float::with_val(53, 1.0), Float::with_val(53, 0.0)),
638 ))
639 .unwrap();
640 let expected_result = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
641 53,
642 (Float::with_val(53, 0.0), Float::with_val(53, 0.0)),
643 ))
644 .unwrap();
645 assert_eq!(value.clone().ln(), expected_result);
646 assert_eq!(value.try_ln().unwrap(), expected_result);
647 }
648 }
649 }
650 }
651
652 mod log10 {
653 use super::*;
654
655 mod native64 {
656 use super::*;
657
658 mod real {
659 use super::*;
660
661 #[test]
662 fn test_f64_log10_valid() {
663 let value = 10.0;
664 let expected_result = 1.0;
665 assert_eq!(value.log10(), expected_result);
666 assert_eq!(value.try_log10().unwrap(), expected_result);
667 }
668
669 #[test]
670 fn test_f64_log10_zero() {
671 let value = 0.0;
672 let result = value.try_log10();
673 assert!(matches!(
674 result,
675 Err(LogarithmRealErrors::Input {
676 source: LogarithmRealInputErrors::ZeroArgument { .. }
677 })
678 ));
679 }
680
681 #[test]
682 fn test_f64_log10_negative() {
683 let value = -10.0;
684 let result = value.try_log10();
685 assert!(matches!(
686 result,
687 Err(LogarithmRealErrors::Input {
688 source: LogarithmRealInputErrors::NegativeArgument { .. }
689 })
690 ));
691 }
692
693 #[test]
694 fn test_f64_log10_one() {
695 let value = 1.0;
696 let expected_result = 0.0;
697 assert_eq!(value.log10(), expected_result);
698 assert_eq!(value.try_log10().unwrap(), expected_result);
699 }
700
701 #[test]
702 fn test_f64_log10_infinity() {
703 let value = f64::INFINITY;
704 let result = value.try_log10();
705 assert!(matches!(
706 result,
707 Err(LogarithmRealErrors::Input {
708 source: LogarithmRealInputErrors::InvalidArgument { .. }
709 })
710 ));
711 }
712
713 #[test]
714 fn test_f64_log10_nan() {
715 let value = f64::NAN;
716 let result = value.try_log10();
717 assert!(matches!(
718 result,
719 Err(LogarithmRealErrors::Input {
720 source: LogarithmRealInputErrors::InvalidArgument { .. }
721 })
722 ));
723 }
724 }
725
726 mod complex {
727 use super::*;
728
729 #[test]
730 fn test_complex_f64_log10_valid() {
731 let value = Complex::new(10.0, 0.0);
732 let expected_result = Complex::new(1.0, 0.0);
733 assert_eq!(value.log10(), expected_result);
734 assert_eq!(value.try_log10().unwrap(), expected_result);
735 }
736
737 #[test]
738 fn test_complex_f64_log10_zero() {
739 let value = Complex::new(0.0, 0.0);
740 let result = value.try_log10();
741 assert!(matches!(
742 result,
743 Err(LogarithmComplexErrors::Input {
744 source: LogarithmComplexInputErrors::ZeroArgument { .. }
745 })
746 ));
747 }
748
749 #[test]
750 fn test_complex_f64_log10_negative() {
751 let value = Complex::new(-10.0, 0.0);
752 let expected_result = Complex::new(1.0, 1.3643763538418412);
753 assert_eq!(value.log10(), expected_result);
754 assert_eq!(value.try_log10().unwrap(), expected_result);
755 }
756
757 #[test]
758 fn test_complex_f64_log10_one() {
759 let value = Complex::new(1.0, 0.0);
760 let expected_result = Complex::new(0.0, 0.0);
761 assert_eq!(value.log10(), expected_result);
762 assert_eq!(value.try_log10().unwrap(), expected_result);
763 }
764
765 #[test]
766 fn test_complex_f64_log10_infinity() {
767 let value = Complex::new(f64::INFINITY, 0.0);
768 let result = value.try_log10();
769 assert!(matches!(
770 result,
771 Err(LogarithmComplexErrors::Input {
772 source: LogarithmComplexInputErrors::InvalidArgument { .. }
773 })
774 ));
775
776 let value = Complex::new(0.0, f64::INFINITY);
777 let result = value.try_log10();
778 assert!(matches!(
779 result,
780 Err(LogarithmComplexErrors::Input {
781 source: LogarithmComplexInputErrors::InvalidArgument { .. }
782 })
783 ));
784 }
785
786 #[test]
787 fn test_complex_f64_log10_nan() {
788 let value = Complex::new(f64::NAN, 0.0);
789 let result = value.try_log10();
790 assert!(matches!(
791 result,
792 Err(LogarithmComplexErrors::Input {
793 source: LogarithmComplexInputErrors::InvalidArgument { .. }
794 })
795 ));
796
797 let value = Complex::new(0.0, f64::NAN);
798 let result = value.try_log10();
799 assert!(matches!(
800 result,
801 Err(LogarithmComplexErrors::Input {
802 source: LogarithmComplexInputErrors::InvalidArgument { .. }
803 })
804 ));
805 }
806 }
807 }
808
809 #[cfg(feature = "rug")]
810 mod rug53 {
811 use super::*;
812 use rug::{Complex, Float};
813
814 mod real {
815 use super::*;
816
817 #[test]
818 fn test_real_log10_valid() {
819 let value =
820 RealRugStrictFinite::<53>::try_new(Float::with_val(53, 10.0)).unwrap();
821 let expected_result =
822 RealRugStrictFinite::<53>::try_new(Float::with_val(53, 1.0)).unwrap();
823 assert_eq!(value.clone().log10(), expected_result);
824 assert_eq!(value.try_log10().unwrap(), expected_result);
825 }
826
827 #[test]
828 fn test_real_log10_zero() {
829 let value =
830 RealRugStrictFinite::<53>::try_new(Float::with_val(53, 0.0)).unwrap();
831 let result = value.try_log10();
832 assert!(matches!(
833 result,
834 Err(LogarithmRealErrors::Input {
835 source: LogarithmRealInputErrors::ZeroArgument { .. }
836 })
837 ));
838 }
839
840 #[test]
841 fn test_real_log10_negative() {
842 let value =
843 RealRugStrictFinite::<53>::try_new(Float::with_val(53, -10.0)).unwrap();
844 let result = value.try_log10();
845 assert!(matches!(
846 result,
847 Err(LogarithmRealErrors::Input {
848 source: LogarithmRealInputErrors::NegativeArgument { .. }
849 })
850 ));
851 }
852
853 #[test]
854 fn test_real_log10_one() {
855 let value =
856 RealRugStrictFinite::<53>::try_new(Float::with_val(53, 1.0)).unwrap();
857 let expected_result =
858 RealRugStrictFinite::<53>::try_new(Float::with_val(53, 0.0)).unwrap();
859 assert_eq!(value.clone().log10(), expected_result);
860 assert_eq!(value.try_log10().unwrap(), expected_result);
861 }
862 }
863
864 mod complex {
865 use super::*;
866
867 #[test]
868 fn test_complex_log10_valid() {
869 let value = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
870 53,
871 (Float::with_val(53, 10.0), Float::with_val(53, 0.0)),
872 ))
873 .unwrap();
874 let expected_result = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
875 53,
876 (Float::with_val(53, 1.0), Float::with_val(53, 0.0)),
877 ))
878 .unwrap();
879 assert_eq!(value.clone().log10(), expected_result);
880 assert_eq!(value.try_log10().unwrap(), expected_result);
881 }
882
883 #[test]
884 fn test_complex_log10_zero() {
885 let value = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
886 53,
887 (Float::with_val(53, 0.0), Float::with_val(53, 0.0)),
888 ))
889 .unwrap();
890 let result = value.try_log10();
891 assert!(matches!(
892 result,
893 Err(LogarithmComplexErrors::Input {
894 source: LogarithmComplexInputErrors::ZeroArgument { .. }
895 })
896 ));
897 }
898
899 #[test]
900 fn test_complex_log10_negative() {
901 let value = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
902 53,
903 (Float::with_val(53, -10.0), Float::with_val(53, 0.0)),
904 ))
905 .unwrap();
906 let expected_result = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
907 53,
908 (
909 Float::with_val(53, 1.0),
910 Float::with_val(53, 1.3643763538418414),
911 ),
912 ))
913 .unwrap();
914 assert_eq!(value.clone().log10(), expected_result);
915 assert_eq!(value.try_log10().unwrap(), expected_result);
916 }
917
918 #[test]
919 fn test_complex_log10_one() {
920 let value = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
921 53,
922 (Float::with_val(53, 1.0), Float::with_val(53, 0.0)),
923 ))
924 .unwrap();
925 let expected_result = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
926 53,
927 (Float::with_val(53, 0.0), Float::with_val(53, 0.0)),
928 ))
929 .unwrap();
930 assert_eq!(value.clone().log10(), expected_result);
931 assert_eq!(value.try_log10().unwrap(), expected_result);
932 }
933 }
934 }
935 }
936
937 mod log2 {
938 use super::*;
939
940 mod native64 {
941 use super::*;
942
943 mod real {
944 use super::*;
945
946 #[test]
947 fn test_f64_log2_valid() {
948 let value = 10.0;
949 let expected_result = std::f64::consts::LOG2_10;
950 assert_eq!(value.log2(), expected_result);
951 assert_eq!(value.try_log2().unwrap(), expected_result);
952 }
953
954 #[test]
955 fn test_f64_log2_zero() {
956 let value = 0.0;
957 let result = value.try_log2();
958 assert!(matches!(
959 result,
960 Err(LogarithmRealErrors::Input {
961 source: LogarithmRealInputErrors::ZeroArgument { .. }
962 })
963 ));
964 }
965
966 #[test]
967 fn test_f64_log2_negative() {
968 let value = -10.0;
969 let result = value.try_log2();
970 assert!(matches!(
971 result,
972 Err(LogarithmRealErrors::Input {
973 source: LogarithmRealInputErrors::NegativeArgument { .. }
974 })
975 ));
976 }
977
978 #[test]
979 fn test_f64_log2_one() {
980 let value = 1.0;
981 let expected_result = 0.0;
982 assert_eq!(value.log2(), expected_result);
983 assert_eq!(value.try_log2().unwrap(), expected_result);
984 }
985
986 #[test]
987 fn test_f64_log2_infinity() {
988 let value = f64::INFINITY;
989 let result = value.try_log2();
990 assert!(matches!(
991 result,
992 Err(LogarithmRealErrors::Input {
993 source: LogarithmRealInputErrors::InvalidArgument { .. }
994 })
995 ));
996 }
997
998 #[test]
999 fn test_f64_log2_nan() {
1000 let value = f64::NAN;
1001 let result = value.try_log2();
1002 assert!(matches!(
1003 result,
1004 Err(LogarithmRealErrors::Input {
1005 source: LogarithmRealInputErrors::InvalidArgument { .. }
1006 })
1007 ));
1008 }
1009 }
1010
1011 mod complex {
1012 use super::*;
1013
1014 #[test]
1015 fn test_complex_f64_log2_valid() {
1016 let value = Complex::new(10.0, 0.0);
1017 let expected_result = Complex::new(3.3219280948873626, 0.0);
1018 assert_eq!(value.log2(), expected_result);
1019 assert_eq!(value.try_log2().unwrap(), expected_result);
1020 }
1021
1022 #[test]
1023 fn test_complex_f64_log2_zero() {
1024 let value = Complex::new(0.0, 0.0);
1025 let result = value.try_log2();
1026 assert!(matches!(
1027 result,
1028 Err(LogarithmComplexErrors::Input {
1029 source: LogarithmComplexInputErrors::ZeroArgument { .. }
1030 })
1031 ));
1032 }
1033
1034 #[test]
1035 fn test_complex_f64_log2_negative() {
1036 let value = Complex::new(-10.0, 0.0);
1037 let expected_result = Complex::new(3.3219280948873626, 4.532360141827194);
1038 assert_eq!(value.log2(), expected_result);
1039 assert_eq!(value.try_log2().unwrap(), expected_result);
1040 }
1041
1042 #[test]
1043 fn test_complex_f64_log2_one() {
1044 let value = Complex::new(1.0, 0.0);
1045 let expected_result = Complex::new(0.0, 0.0);
1046 assert_eq!(value.log2(), expected_result);
1047 assert_eq!(value.try_log2().unwrap(), expected_result);
1048 }
1049
1050 #[test]
1051 fn test_complex_f64_log2_infinity() {
1052 let value = Complex::new(f64::INFINITY, 0.0);
1053 let result = value.try_log2();
1054 assert!(matches!(
1055 result,
1056 Err(LogarithmComplexErrors::Input {
1057 source: LogarithmComplexInputErrors::InvalidArgument { .. }
1058 })
1059 ));
1060
1061 let value = Complex::new(0.0, f64::INFINITY);
1062 let result = value.try_log2();
1063 assert!(matches!(
1064 result,
1065 Err(LogarithmComplexErrors::Input {
1066 source: LogarithmComplexInputErrors::InvalidArgument { .. }
1067 })
1068 ));
1069 }
1070
1071 #[test]
1072 fn test_complex_f64_log2_nan() {
1073 let value = Complex::new(f64::NAN, 0.0);
1074 let result = value.try_log2();
1075 assert!(matches!(
1076 result,
1077 Err(LogarithmComplexErrors::Input {
1078 source: LogarithmComplexInputErrors::InvalidArgument { .. }
1079 })
1080 ));
1081
1082 let value = Complex::new(0.0, f64::NAN);
1083 let result = value.try_log2();
1084 assert!(matches!(
1085 result,
1086 Err(LogarithmComplexErrors::Input {
1087 source: LogarithmComplexInputErrors::InvalidArgument { .. }
1088 })
1089 ));
1090 }
1091 }
1092 }
1093
1094 #[cfg(feature = "rug")]
1095 mod rug53 {
1096 use super::*;
1097 use rug::{Complex, Float};
1098
1099 mod real {
1100 use super::*;
1101
1102 #[test]
1103 fn test_real_log2_valid() {
1104 let value =
1105 RealRugStrictFinite::<53>::try_new(Float::with_val(53, 10.0)).unwrap();
1106 let expected_result = RealRugStrictFinite::<53>::try_new(Float::with_val(
1107 53,
1108 std::f64::consts::LOG2_10,
1109 ))
1110 .unwrap();
1111 assert_eq!(value.clone().log2(), expected_result);
1112 assert_eq!(value.try_log2().unwrap(), expected_result);
1113 }
1114
1115 #[test]
1116 fn test_real_log2_zero() {
1117 let value =
1118 RealRugStrictFinite::<53>::try_new(Float::with_val(53, 0.0)).unwrap();
1119 let result = value.try_log2();
1120 assert!(matches!(
1121 result,
1122 Err(LogarithmRealErrors::Input {
1123 source: LogarithmRealInputErrors::ZeroArgument { .. }
1124 })
1125 ));
1126 }
1127
1128 #[test]
1129 fn test_real_log2_negative() {
1130 let value =
1131 RealRugStrictFinite::<53>::try_new(Float::with_val(53, -10.0)).unwrap();
1132 let result = value.try_log2();
1133 assert!(matches!(
1134 result,
1135 Err(LogarithmRealErrors::Input {
1136 source: LogarithmRealInputErrors::NegativeArgument { .. }
1137 })
1138 ));
1139 }
1140
1141 #[test]
1142 fn test_real_log2_one() {
1143 let value =
1144 RealRugStrictFinite::<53>::try_new(Float::with_val(53, 1.0)).unwrap();
1145 let expected_result =
1146 RealRugStrictFinite::<53>::try_new(Float::with_val(53, 0.0)).unwrap();
1147 assert_eq!(value.clone().log2(), expected_result);
1148 assert_eq!(value.try_log2().unwrap(), expected_result);
1149 }
1150 }
1151
1152 mod complex {
1153 use super::*;
1154
1155 #[test]
1156 fn test_complex_log2_valid() {
1157 let value = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1158 53,
1159 (Float::with_val(53, 10.0), Float::with_val(53, 0.0)),
1160 ))
1161 .unwrap();
1162 let expected_result = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1163 53,
1164 (
1165 Float::with_val(53, 3.3219280948873626),
1166 Float::with_val(53, 0.0),
1167 ),
1168 ))
1169 .unwrap();
1170 assert_eq!(value.clone().log2(), expected_result);
1171 assert_eq!(value.try_log2().unwrap(), expected_result);
1172 }
1173
1174 #[test]
1175 fn test_complex_log2_zero() {
1176 let value = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1177 53,
1178 (Float::with_val(53, 0.0), Float::with_val(53, 0.0)),
1179 ))
1180 .unwrap();
1181 let result = value.try_log2();
1182 assert!(matches!(
1183 result,
1184 Err(LogarithmComplexErrors::Input {
1185 source: LogarithmComplexInputErrors::ZeroArgument { .. }
1186 })
1187 ));
1188 }
1189
1190 #[test]
1191 fn test_complex_log2_negative() {
1192 let value = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1193 53,
1194 (Float::with_val(53, -10.0), Float::with_val(53, 0.0)),
1195 ))
1196 .unwrap();
1197 let expected_result = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1198 53,
1199 (
1200 Float::with_val(53, 3.3219280948873626),
1201 Float::with_val(53, 4.532360141827194),
1202 ),
1203 ))
1204 .unwrap();
1205 assert_eq!(value.clone().log2(), expected_result);
1206 assert_eq!(value.try_log2().unwrap(), expected_result);
1207 }
1208
1209 #[test]
1210 fn test_complex_log2_one() {
1211 let value = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1212 53,
1213 (Float::with_val(53, 1.0), Float::with_val(53, 0.0)),
1214 ))
1215 .unwrap();
1216 let expected_result = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1217 53,
1218 (Float::with_val(53, 0.0), Float::with_val(53, 0.0)),
1219 ))
1220 .unwrap();
1221 assert_eq!(value.clone().log2(), expected_result);
1222 assert_eq!(value.try_log2().unwrap(), expected_result);
1223 }
1224 }
1225 }
1226 }
1227}
1228