1use crate::{
18 error::{CoreError, CoreResult, ErrorContext},
19 numeric::precision_tracking::PrecisionContext,
20 validation::check_positive,
21};
22use num_bigint::BigInt;
23use rug::{
24 float::Round, ops::Pow, Complex as RugComplex, Float as RugFloat, Integer as RugInteger,
25 Rational as RugRational,
26};
27use std::cmp::Ordering;
28use std::fmt;
29use std::ops::{Add, Div, Mul, Neg, Sub};
30use std::str::FromStr;
31use std::sync::RwLock;
32
33static DEFAULT_PRECISION: RwLock<u32> = RwLock::new(256);
35
36#[allow(dead_code)]
38pub fn get_defaultprecision() -> u32 {
39 *DEFAULT_PRECISION.read().expect("Operation failed")
40}
41
42#[allow(dead_code)]
44pub fn setprecision(prec: u32) -> CoreResult<()> {
45 check_positive(prec as f64, "precision")?;
46 *DEFAULT_PRECISION.write().expect("Operation failed") = prec;
47 Ok(())
48}
49
50#[derive(Debug, Clone)]
52pub struct ArbitraryPrecisionContext {
53 pub floatprecision: u32,
55 pub maxprecision: u32,
57 pub rounding_mode: RoundingMode,
59 pub trackprecision: bool,
61 pub precision_context: Option<PrecisionContext>,
63}
64
65#[derive(Debug, Clone, Copy, PartialEq, Eq)]
67pub enum RoundingMode {
68 Nearest,
70 Zero,
72 Up,
74 Down,
76 Away,
78}
79
80impl RoundingMode {
81 fn to_rug_round(self) -> Round {
83 match self {
84 RoundingMode::Nearest => Round::Nearest,
85 RoundingMode::Zero => Round::Zero,
86 RoundingMode::Up => Round::Up,
87 RoundingMode::Down => Round::Down,
88 RoundingMode::Away => Round::Up, }
90 }
91}
92
93impl Default for ArbitraryPrecisionContext {
94 fn default() -> Self {
95 Self {
96 floatprecision: get_defaultprecision(),
97 maxprecision: 4096,
98 rounding_mode: RoundingMode::Nearest,
99 trackprecision: false,
100 precision_context: None,
101 }
102 }
103}
104
105impl ArbitraryPrecisionContext {
106 pub fn withprecision(precision: u32) -> CoreResult<Self> {
108 check_positive(precision as f64, "precision")?;
109 Ok(Self {
110 floatprecision: precision,
111 ..Default::default()
112 })
113 }
114
115 pub fn withprecision_tracking(precision: u32) -> CoreResult<Self> {
117 let mut ctx = Self::withprecision(precision)?;
118 ctx.trackprecision = true;
119 let mut precision_ctx = PrecisionContext::new();
120 precision_ctx.precision = precision as f64 / 3.32; ctx.precision_context = Some(precision_ctx);
122 Ok(ctx)
123 }
124
125 pub fn with_rounding(mut self, mode: RoundingMode) -> Self {
127 self.rounding_mode = mode;
128 self
129 }
130
131 pub fn with_maxprecision(mut self, maxprec: u32) -> Self {
133 self.maxprecision = maxprec;
134 self
135 }
136}
137
138#[derive(Clone, PartialEq, Eq)]
140pub struct ArbitraryInt {
141 value: RugInteger,
142}
143
144impl ArbitraryInt {
145 pub fn new() -> Self {
147 Self {
148 value: RugInteger::new(),
149 }
150 }
151
152 pub fn from_i64(n: i64) -> Self {
154 Self {
155 value: RugInteger::from(n),
156 }
157 }
158
159 pub fn from_str_radix(s: &str, radix: i32) -> CoreResult<Self> {
161 RugInteger::parse_radix(s, radix)
162 .map(|incomplete| {
163 let value = RugInteger::from(incomplete);
164 Self { value }
165 })
166 .map_err(|_| {
167 CoreError::ValidationError(ErrorContext::new(format!(
168 "Failed to parse integer from string: {}",
169 s
170 )))
171 })
172 }
173
174 pub fn to_bigint(&self) -> BigInt {
176 BigInt::from_str(&self.value.to_string()).expect("Operation failed")
177 }
178
179 pub fn is_probably_prime(&self, reps: u32) -> bool {
181 self.value.is_probably_prime(reps) != rug::integer::IsPrime::No
182 }
183
184 pub fn factorial(n: u32) -> Self {
186 let mut result = RugInteger::from(1);
187 for i in 2..=n {
188 result *= i;
189 }
190 Self { value: result }
191 }
192
193 pub fn binomial(n: u32, k: u32) -> Self {
195 if k > n {
196 return Self::new();
197 }
198 let mut result = RugInteger::from(1);
199 for i in 0..k {
200 result *= n - i;
201 result /= i + 1;
202 }
203 Self { value: result }
204 }
205
206 pub fn gcd(&self, other: &Self) -> Self {
208 Self {
209 value: self.value.clone().gcd(&other.value),
210 }
211 }
212
213 pub fn lcm(&self, other: &Self) -> Self {
215 if self.value.is_zero() || other.value.is_zero() {
216 return Self::new();
217 }
218 let gcd = self.gcd(other);
219 let product = RugInteger::from(&self.value * &other.value);
221 Self {
222 value: product / gcd.value,
223 }
224 }
225
226 pub fn mod_pow(&self, exp: &Self, modulus: &Self) -> CoreResult<Self> {
228 if modulus.value.is_zero() {
229 return Err(CoreError::DomainError(ErrorContext::new(
230 "Modulus cannot be zero",
231 )));
232 }
233 Ok(Self {
234 value: self
235 .value
236 .clone()
237 .pow_mod(&exp.value, &modulus.value)
238 .expect("Operation failed"),
239 })
240 }
241
242 pub fn abs(&self) -> Self {
244 Self {
245 value: self.value.clone().abs(),
246 }
247 }
248
249 pub fn signum(&self) -> i32 {
251 self.value.cmp0() as i32
252 }
253}
254
255impl fmt::Display for ArbitraryInt {
256 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
257 write!(f, "{}", self.value)
258 }
259}
260
261impl fmt::Debug for ArbitraryInt {
262 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
263 write!(f, "ArbitraryInt({})", self.value)
264 }
265}
266
267impl Default for ArbitraryInt {
268 fn default() -> Self {
269 Self::new()
270 }
271}
272
273impl Add for ArbitraryInt {
275 type Output = Self;
276 fn add(self, rhs: Self) -> Self::Output {
277 Self {
278 value: self.value + rhs.value,
279 }
280 }
281}
282
283impl Sub for ArbitraryInt {
284 type Output = Self;
285 fn sub(self, rhs: Self) -> Self::Output {
286 Self {
287 value: self.value - rhs.value,
288 }
289 }
290}
291
292impl Mul for ArbitraryInt {
293 type Output = Self;
294 fn mul(self, rhs: Self) -> Self::Output {
295 Self {
296 value: self.value * rhs.value,
297 }
298 }
299}
300
301impl Div for ArbitraryInt {
302 type Output = Self;
303 fn div(self, rhs: Self) -> Self::Output {
304 Self {
305 value: self.value / rhs.value,
306 }
307 }
308}
309
310impl Neg for ArbitraryInt {
311 type Output = Self;
312 fn neg(self) -> Self::Output {
313 Self { value: -self.value }
314 }
315}
316
317#[derive(Clone)]
319pub struct ArbitraryFloat {
320 value: RugFloat,
321 context: ArbitraryPrecisionContext,
322}
323
324impl ArbitraryFloat {
325 pub fn new() -> Self {
327 let prec = get_defaultprecision();
328 Self {
329 value: RugFloat::new(prec),
330 context: ArbitraryPrecisionContext::default(),
331 }
332 }
333
334 pub fn withprecision(prec: u32) -> CoreResult<Self> {
336 let context = ArbitraryPrecisionContext::withprecision(prec)?;
337 Ok(Self {
338 value: RugFloat::new(prec),
339 context,
340 })
341 }
342
343 pub fn with_context(context: ArbitraryPrecisionContext) -> Self {
345 Self {
346 value: RugFloat::new(context.floatprecision),
347 context,
348 }
349 }
350
351 pub fn from_f64(value: f64) -> Self {
353 let prec = get_defaultprecision();
354 Self {
355 value: RugFloat::with_val(prec, value),
356 context: ArbitraryPrecisionContext::default(),
357 }
358 }
359
360 pub fn from_f64_withprecision(value: f64, prec: u32) -> CoreResult<Self> {
362 let context = ArbitraryPrecisionContext::withprecision(prec)?;
363 Ok(Self {
364 value: RugFloat::with_val(prec, value),
365 context,
366 })
367 }
368
369 pub fn from_strprec(s: &str, prec: u32) -> CoreResult<Self> {
371 let context = ArbitraryPrecisionContext::withprecision(prec)?;
372 RugFloat::parse(s)
373 .map(|incomplete| Self {
374 value: RugFloat::with_val(prec, incomplete),
375 context,
376 })
377 .map_err(|e| CoreError::ValidationError(ErrorContext::new(format!("{e}"))))
378 }
379
380 pub fn precision(&self) -> u32 {
382 self.value.prec()
383 }
384
385 pub fn decimalprecision(&self) -> u32 {
387 (self.value.prec() as f64 / 3.32) as u32
388 }
389
390 pub fn setprecision(&self, prec: u32) -> CoreResult<Self> {
392 let mut context = self.context.clone();
393 context.floatprecision = prec;
394 Ok(Self {
395 value: RugFloat::with_val(prec, &self.value),
396 context,
397 })
398 }
399
400 pub fn to_f64(&self) -> f64 {
402 self.value.to_f64()
403 }
404
405 pub fn is_finite(&self) -> bool {
407 self.value.is_finite()
408 }
409
410 pub fn is_infinite(&self) -> bool {
412 self.value.is_infinite()
413 }
414
415 pub fn is_nan(&self) -> bool {
417 self.value.is_nan()
418 }
419
420 pub fn is_zero(&self) -> bool {
422 self.value.is_zero()
423 }
424
425 pub fn abs(&self) -> Self {
427 let mut result = self.clone();
428 result.value.abs_mut();
429 result
430 }
431
432 pub fn sqrt(&self) -> CoreResult<Self> {
434 if self.value.is_sign_negative() && !self.value.is_zero() {
435 return Err(CoreError::DomainError(ErrorContext::new(
436 "Square root of negative number",
437 )));
438 }
439 let mut result = self.clone();
440 result.value.sqrt_mut();
441 Ok(result)
442 }
443
444 pub fn ln(&self) -> CoreResult<Self> {
446 if self.value.is_sign_negative() || self.value.is_zero() {
447 return Err(CoreError::DomainError(ErrorContext::new(
448 "Logarithm of non-positive number",
449 )));
450 }
451 let mut result = self.clone();
452 result.value.ln_mut();
453 Ok(result)
454 }
455
456 pub fn exp(&self) -> Self {
458 let mut result = self.clone();
459 result.value.exp_mut();
460 result
461 }
462
463 pub fn pow(&self, exp: &Self) -> Self {
465 let mut result = self.clone();
466 let pow_result = self.value.clone().pow(&exp.value);
467 result.value = RugFloat::with_val(self.context.floatprecision, pow_result);
468 result
469 }
470
471 pub fn sin(&self) -> Self {
473 let mut result = self.clone();
474 result.value.sin_mut();
475 result
476 }
477
478 pub fn cos(&self) -> Self {
480 let mut result = self.clone();
481 result.value.cos_mut();
482 result
483 }
484
485 pub fn tan(&self) -> Self {
487 let mut result = self.clone();
488 result.value.tan_mut();
489 result
490 }
491
492 pub fn asin(&self) -> CoreResult<Self> {
494 if self.value.clone().abs() > 1 {
495 return Err(CoreError::DomainError(ErrorContext::new(
496 "Arcsine argument out of range [-1, 1]",
497 )));
498 }
499 let mut result = self.clone();
500 result.value.asin_mut();
501 Ok(result)
502 }
503
504 pub fn acos(&self) -> CoreResult<Self> {
506 if self.value.clone().abs() > 1 {
507 return Err(CoreError::DomainError(ErrorContext::new(
508 "Arccosine argument out of range [-1, 1]",
509 )));
510 }
511 let mut result = self.clone();
512 result.value.acos_mut();
513 Ok(result)
514 }
515
516 pub fn atan(&self) -> Self {
518 let mut result = self.clone();
519 result.value.atan_mut();
520 result
521 }
522
523 pub fn atan2(&self, x: &Self) -> Self {
525 let mut result = self.clone();
526 result.value = RugFloat::with_val(
527 self.context.floatprecision,
528 self.value.clone().atan2(&x.value),
529 );
530 result
531 }
532
533 pub fn sinh(&self) -> Self {
535 let mut result = self.clone();
536 result.value.sinh_mut();
537 result
538 }
539
540 pub fn cosh(&self) -> Self {
542 let mut result = self.clone();
543 result.value.cosh_mut();
544 result
545 }
546
547 pub fn tanh(&self) -> Self {
549 let mut result = self.clone();
550 result.value.tanh_mut();
551 result
552 }
553
554 pub fn prec_2(prec: u32) -> CoreResult<Self> {
556 let context = ArbitraryPrecisionContext::withprecision(prec)?;
557 let value = RugFloat::with_val(prec, rug::float::Constant::Pi);
558 Ok(Self { value, context })
559 }
560
561 pub fn prec_3(prec: u32) -> CoreResult<Self> {
562 let one = Self::from_f64_withprecision(1.0, prec)?;
563 Ok(one.exp())
564 }
565
566 pub fn prec_4(prec: u32) -> CoreResult<Self> {
567 let context = ArbitraryPrecisionContext::withprecision(prec)?;
568 let value = RugFloat::with_val(prec, rug::float::Constant::Log2);
569 Ok(Self { value, context })
570 }
571}
572
573impl fmt::Display for ArbitraryFloat {
574 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
575 write!(f, "{}", self.value)
576 }
577}
578
579impl fmt::Debug for ArbitraryFloat {
580 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
581 write!(
582 f,
583 "ArbitraryFloat({}, {} bits)",
584 self.value,
585 self.precision()
586 )
587 }
588}
589
590impl PartialEq for ArbitraryFloat {
591 fn eq(&self, other: &Self) -> bool {
592 self.value.eq(&other.value)
593 }
594}
595
596impl PartialOrd for ArbitraryFloat {
597 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
598 self.value.partial_cmp(&other.value)
599 }
600}
601
602impl Default for ArbitraryFloat {
603 fn default() -> Self {
604 Self::new()
605 }
606}
607
608impl Add for ArbitraryFloat {
610 type Output = Self;
611 fn add(self, rhs: Self) -> Self::Output {
612 Self {
613 value: self.value + rhs.value,
614 context: self.context,
615 }
616 }
617}
618
619impl Sub for ArbitraryFloat {
620 type Output = Self;
621 fn sub(self, rhs: Self) -> Self::Output {
622 Self {
623 value: self.value - rhs.value,
624 context: self.context,
625 }
626 }
627}
628
629impl Mul for ArbitraryFloat {
630 type Output = Self;
631 fn mul(self, rhs: Self) -> Self::Output {
632 Self {
633 value: self.value * rhs.value,
634 context: self.context,
635 }
636 }
637}
638
639impl Div for ArbitraryFloat {
640 type Output = Self;
641 fn div(self, rhs: Self) -> Self::Output {
642 Self {
643 value: self.value / rhs.value,
644 context: self.context,
645 }
646 }
647}
648
649impl Neg for ArbitraryFloat {
650 type Output = Self;
651 fn neg(self) -> Self::Output {
652 Self {
653 value: -self.value,
654 context: self.context,
655 }
656 }
657}
658
659#[derive(Clone, PartialEq, Eq)]
661pub struct ArbitraryRational {
662 value: RugRational,
663}
664
665impl ArbitraryRational {
666 pub fn new() -> Self {
668 Self {
669 value: RugRational::new(),
670 }
671 }
672
673 pub fn num(num: i64, den: i64) -> CoreResult<Self> {
675 if den == 0 {
676 return Err(CoreError::DomainError(ErrorContext::new(
677 "Denominator cannot be zero",
678 )));
679 }
680 Ok(Self {
681 value: RugRational::from((num, den)),
682 })
683 }
684
685 pub fn num_2(num: &ArbitraryInt, den: &ArbitraryInt) -> CoreResult<Self> {
687 if den.value.is_zero() {
688 return Err(CoreError::DomainError(ErrorContext::new(
689 "Denominator cannot be zero",
690 )));
691 }
692 Ok(Self {
693 value: RugRational::from((&num.value, &den.value)),
694 })
695 }
696
697 #[deprecated(note = "Use str::parse() instead")]
700 pub fn parse_rational(s: &str) -> CoreResult<Self> {
701 s.parse()
702 }
703
704 pub fn to_f64(&self) -> f64 {
706 self.value.to_f64()
707 }
708
709 pub fn to_arbitrary_float(&self, prec: u32) -> CoreResult<ArbitraryFloat> {
711 let context = ArbitraryPrecisionContext::withprecision(prec)?;
712 Ok(ArbitraryFloat {
713 value: RugFloat::with_val(prec, &self.value),
714 context,
715 })
716 }
717
718 pub fn numerator(&self) -> ArbitraryInt {
720 ArbitraryInt {
721 value: self.value.numer().clone(),
722 }
723 }
724
725 pub fn denominator(&self) -> ArbitraryInt {
727 ArbitraryInt {
728 value: self.value.denom().clone(),
729 }
730 }
731
732 pub fn abs(&self) -> Self {
734 Self {
735 value: self.value.clone().abs(),
736 }
737 }
738
739 pub fn recip(&self) -> CoreResult<Self> {
741 if self.value.is_zero() {
742 return Err(CoreError::DomainError(ErrorContext::new(
743 "Cannot take reciprocal of zero",
744 )));
745 }
746 Ok(Self {
747 value: self.value.clone().recip(),
748 })
749 }
750}
751
752impl fmt::Display for ArbitraryRational {
753 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
754 write!(f, "{}", self.value)
755 }
756}
757
758impl fmt::Debug for ArbitraryRational {
759 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
760 write!(f, "ArbitraryRational({})", self.value)
761 }
762}
763
764impl Default for ArbitraryRational {
765 fn default() -> Self {
766 Self::new()
767 }
768}
769
770impl FromStr for ArbitraryRational {
771 type Err = CoreError;
772
773 fn from_str(s: &str) -> Result<Self, Self::Err> {
774 RugRational::from_str(s)
775 .map(|value| Self { value })
776 .map_err(|_| {
777 CoreError::ValidationError(ErrorContext::new(format!(
778 "Failed to parse rational from string: {}",
779 s
780 )))
781 })
782 }
783}
784
785impl Add for ArbitraryRational {
787 type Output = Self;
788 fn add(self, rhs: Self) -> Self::Output {
789 Self {
790 value: self.value + rhs.value,
791 }
792 }
793}
794
795impl Sub for ArbitraryRational {
796 type Output = Self;
797 fn sub(self, rhs: Self) -> Self::Output {
798 Self {
799 value: self.value - rhs.value,
800 }
801 }
802}
803
804impl Mul for ArbitraryRational {
805 type Output = Self;
806 fn mul(self, rhs: Self) -> Self::Output {
807 Self {
808 value: self.value * rhs.value,
809 }
810 }
811}
812
813impl Div for ArbitraryRational {
814 type Output = Self;
815 fn div(self, rhs: Self) -> Self::Output {
816 Self {
817 value: self.value / rhs.value,
818 }
819 }
820}
821
822impl Neg for ArbitraryRational {
823 type Output = Self;
824 fn neg(self) -> Self::Output {
825 Self { value: -self.value }
826 }
827}
828
829#[derive(Clone)]
831pub struct ArbitraryComplex {
832 value: RugComplex,
833 context: ArbitraryPrecisionContext,
834}
835
836impl ArbitraryComplex {
837 pub fn new() -> Self {
839 let prec = get_defaultprecision();
840 Self {
841 value: RugComplex::new(prec),
842 context: ArbitraryPrecisionContext::default(),
843 }
844 }
845
846 pub fn prec(prec: u32) -> CoreResult<Self> {
848 let context = ArbitraryPrecisionContext::withprecision(prec)?;
849 Ok(Self {
850 value: RugComplex::new(prec),
851 context,
852 })
853 }
854
855 pub fn re(re: &ArbitraryFloat, im: &ArbitraryFloat) -> Self {
857 let prec = re.precision().max(im.precision());
858 let context = re.context.clone();
859 Self {
860 value: RugComplex::with_val(prec, (&re.value, &im.value)),
861 context,
862 }
863 }
864
865 pub fn re_2(re: f64, im: f64) -> Self {
867 let prec = get_defaultprecision();
868 Self {
869 value: RugComplex::with_val(prec, (re, im)),
870 context: ArbitraryPrecisionContext::default(),
871 }
872 }
873
874 pub fn real(&self) -> ArbitraryFloat {
876 ArbitraryFloat {
877 value: self.value.real().clone(),
878 context: self.context.clone(),
879 }
880 }
881
882 pub fn imag(&self) -> ArbitraryFloat {
884 ArbitraryFloat {
885 value: self.value.imag().clone(),
886 context: self.context.clone(),
887 }
888 }
889
890 pub fn abs(&self) -> ArbitraryFloat {
892 let mut result = ArbitraryFloat::with_context(self.context.clone());
893 result.value = RugFloat::with_val(self.context.floatprecision, self.value.abs_ref());
894 result
895 }
896
897 pub fn arg(&self) -> ArbitraryFloat {
899 let mut result = ArbitraryFloat::with_context(self.context.clone());
900 result.value = RugFloat::with_val(self.context.floatprecision, self.value.arg_ref());
901 result
902 }
903
904 pub fn conj(&self) -> Self {
906 let mut result = self.clone();
907 result.value.conj_mut();
908 result
909 }
910
911 pub fn ln(&self) -> Self {
913 let mut result = self.clone();
914 result.value.ln_mut();
915 result
916 }
917
918 pub fn exp(&self) -> Self {
920 let mut result = self.clone();
921 result.value.exp_mut();
922 result
923 }
924
925 pub fn pow(&self, exp: &Self) -> Self {
927 let ln_self = self.ln();
929 let product = ln_self * exp.clone();
930 product.exp()
931 }
932
933 pub fn sqrt(&self) -> Self {
935 let mut result = self.clone();
936 result.value.sqrt_mut();
937 result
938 }
939}
940
941impl fmt::Display for ArbitraryComplex {
942 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
943 let re = self.value.real();
944 let im = self.value.imag();
945 if im.is_sign_positive() {
946 write!(f, "{} + {}i", re, im)
947 } else {
948 write!(f, "{} - {}i", re, -im.clone())
949 }
950 }
951}
952
953impl fmt::Debug for ArbitraryComplex {
954 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
955 write!(
956 f,
957 "ArbitraryComplex({}, {} bits)",
958 self, self.context.floatprecision
959 )
960 }
961}
962
963impl PartialEq for ArbitraryComplex {
964 fn eq(&self, other: &Self) -> bool {
965 self.value.eq(&other.value)
966 }
967}
968
969impl Default for ArbitraryComplex {
970 fn default() -> Self {
971 Self::new()
972 }
973}
974
975impl Add for ArbitraryComplex {
977 type Output = Self;
978 fn add(self, rhs: Self) -> Self::Output {
979 Self {
980 value: self.value + rhs.value,
981 context: self.context,
982 }
983 }
984}
985
986impl Sub for ArbitraryComplex {
987 type Output = Self;
988 fn sub(self, rhs: Self) -> Self::Output {
989 Self {
990 value: self.value - rhs.value,
991 context: self.context,
992 }
993 }
994}
995
996impl Mul for ArbitraryComplex {
997 type Output = Self;
998 fn mul(self, rhs: Self) -> Self::Output {
999 Self {
1000 value: self.value * rhs.value,
1001 context: self.context,
1002 }
1003 }
1004}
1005
1006impl Div for ArbitraryComplex {
1007 type Output = Self;
1008 fn div(self, rhs: Self) -> Self::Output {
1009 Self {
1010 value: self.value / rhs.value,
1011 context: self.context,
1012 }
1013 }
1014}
1015
1016impl Neg for ArbitraryComplex {
1017 type Output = Self;
1018 fn neg(self) -> Self::Output {
1019 Self {
1020 value: -self.value,
1021 context: self.context,
1022 }
1023 }
1024}
1025
1026pub trait ToArbitraryPrecision {
1028 type ArbitraryType;
1030
1031 fn to_arbitrary(&self) -> Self::ArbitraryType;
1033
1034 fn to_arbitraryprec(&self, prec: u32) -> CoreResult<Self::ArbitraryType>;
1036}
1037
1038impl ToArbitraryPrecision for i32 {
1039 type ArbitraryType = ArbitraryInt;
1040
1041 fn to_arbitrary(&self) -> Self::ArbitraryType {
1042 ArbitraryInt::from_i64(*self as i64)
1043 }
1044
1045 fn to_arbitraryprec(&self, prec: u32) -> CoreResult<Self::ArbitraryType> {
1046 Ok(self.to_arbitrary())
1047 }
1048}
1049
1050impl ToArbitraryPrecision for i64 {
1051 type ArbitraryType = ArbitraryInt;
1052
1053 fn to_arbitrary(&self) -> Self::ArbitraryType {
1054 ArbitraryInt::from_i64(*self)
1055 }
1056
1057 fn to_arbitraryprec(&self, prec: u32) -> CoreResult<Self::ArbitraryType> {
1058 Ok(self.to_arbitrary())
1059 }
1060}
1061
1062impl ToArbitraryPrecision for f32 {
1063 type ArbitraryType = ArbitraryFloat;
1064
1065 fn to_arbitrary(&self) -> Self::ArbitraryType {
1066 ArbitraryFloat::from_f64(*self as f64)
1067 }
1068
1069 fn to_arbitraryprec(&self, prec: u32) -> CoreResult<Self::ArbitraryType> {
1070 ArbitraryFloat::from_f64_withprecision(*self as f64, prec)
1071 }
1072}
1073
1074impl ToArbitraryPrecision for f64 {
1075 type ArbitraryType = ArbitraryFloat;
1076
1077 fn to_arbitrary(&self) -> Self::ArbitraryType {
1078 ArbitraryFloat::from_f64(*self)
1079 }
1080
1081 fn to_arbitraryprec(&self, prec: u32) -> CoreResult<Self::ArbitraryType> {
1082 ArbitraryFloat::from_f64_withprecision(*self, prec)
1083 }
1084}
1085
1086pub struct ArbitraryPrecisionBuilder {
1088 context: ArbitraryPrecisionContext,
1089}
1090
1091impl ArbitraryPrecisionBuilder {
1092 pub fn new() -> Self {
1094 Self {
1095 context: ArbitraryPrecisionContext::default(),
1096 }
1097 }
1098
1099 pub fn precision(mut self, prec: u32) -> Self {
1101 self.context.floatprecision = prec;
1102 self
1103 }
1104
1105 pub fn decimalprecision(mut self, digits: u32) -> Self {
1107 self.context.floatprecision = ((digits as f64) * 3.32) as u32;
1108 self
1109 }
1110
1111 pub fn rounding(mut self, mode: RoundingMode) -> Self {
1113 self.context.rounding_mode = mode;
1114 self
1115 }
1116
1117 pub fn trackprecision(mut self, track: bool) -> Self {
1119 self.context.trackprecision = track;
1120 if track && self.context.precision_context.is_none() {
1121 let mut precision_ctx = PrecisionContext::new();
1122 precision_ctx.precision = self.context.floatprecision as f64 / 3.32;
1123 self.context.precision_context = Some(precision_ctx);
1124 }
1125 self
1126 }
1127
1128 pub fn build_float(self) -> ArbitraryFloat {
1130 ArbitraryFloat::with_context(self.context)
1131 }
1132
1133 pub fn build_complex(self) -> CoreResult<ArbitraryComplex> {
1135 ArbitraryComplex::prec(self.context.floatprecision)
1136 }
1137
1138 pub fn calculate<F, R>(self, f: F) -> R
1140 where
1141 F: FnOnce(&ArbitraryPrecisionContext) -> R,
1142 {
1143 f(&self.context)
1144 }
1145}
1146
1147impl Default for ArbitraryPrecisionBuilder {
1148 fn default() -> Self {
1149 Self::new()
1150 }
1151}
1152
1153pub mod utils {
1155 use super::*;
1156
1157 pub fn pi(prec: u32) -> CoreResult<ArbitraryFloat> {
1159 ArbitraryFloat::prec_2(prec)
1160 }
1161
1162 pub fn e(prec: u32) -> CoreResult<ArbitraryFloat> {
1164 ArbitraryFloat::prec_3(prec)
1165 }
1166
1167 pub fn ln2(prec: u32) -> CoreResult<ArbitraryFloat> {
1169 ArbitraryFloat::prec_4(prec)
1170 }
1171
1172 pub fn sqrt2(prec: u32) -> CoreResult<ArbitraryFloat> {
1174 let two = ArbitraryFloat::from_f64_withprecision(2.0, prec)?;
1175 two.sqrt()
1176 }
1177
1178 pub fn golden_ratio(prec: u32) -> CoreResult<ArbitraryFloat> {
1180 let one = ArbitraryFloat::from_f64_withprecision(1.0, prec)?;
1181 let five = ArbitraryFloat::from_f64_withprecision(5.0, prec)?;
1182 let sqrt5 = five.sqrt()?;
1183 let two = ArbitraryFloat::from_f64_withprecision(2.0, prec)?;
1184 Ok((one + sqrt5) / two)
1185 }
1186
1187 pub fn factorial(n: u32) -> ArbitraryInt {
1189 ArbitraryInt::factorial(n)
1190 }
1191
1192 pub fn binomial(n: u32, k: u32) -> ArbitraryInt {
1194 ArbitraryInt::binomial(n, k)
1195 }
1196
1197 pub fn is_probably_prime(n: &ArbitraryInt, certainty: u32) -> bool {
1199 n.is_probably_prime(certainty)
1200 }
1201}
1202
1203#[cfg(test)]
1204mod tests {
1205 use super::*;
1206
1207 #[test]
1208 fn test_arbitrary_int_basic() {
1209 let a = ArbitraryInt::from_i64(123);
1210 let b = ArbitraryInt::from_i64(456);
1211 let sum = a.clone() + b.clone();
1212 assert_eq!(sum.to_string(), "579");
1213
1214 let product = a.clone() * b.clone();
1215 assert_eq!(product.to_string(), "56088");
1216
1217 let factorial = ArbitraryInt::factorial(20);
1218 assert_eq!(factorial.to_string(), "2432902008176640000");
1219 }
1220
1221 #[test]
1222 fn test_arbitrary_float_basic() {
1223 let a = ArbitraryFloat::from_f64_withprecision(1.0, 128).expect("Operation failed");
1224 let b = ArbitraryFloat::from_f64_withprecision(3.0, 128).expect("Operation failed");
1225 let c = a / b;
1226
1227 let c_str = c.to_string();
1229 assert!(c_str.starts_with("3.333333333333333") || c_str.starts_with("0.333333333333333"));
1231 assert!(c_str.len() > 20); }
1233
1234 #[test]
1235 fn test_arbitrary_rational() {
1236 let r = ArbitraryRational::num(22, 7).expect("Operation failed");
1237 assert_eq!(r.to_string(), "22/7");
1238
1239 let a = ArbitraryRational::num(1, 3).expect("Operation failed");
1240 let b = ArbitraryRational::num(1, 6).expect("Operation failed");
1241 let sum = a + b;
1242 assert_eq!(sum.to_string(), "1/2");
1243 }
1244
1245 #[test]
1246 fn test_arbitrary_complex() {
1247 let z = ArbitraryComplex::re_2(3.0, 4.0);
1248 let mag = z.abs();
1249 assert!((mag.to_f64() - 5.0).abs() < 1e-10);
1250
1251 let conj = z.conj();
1252 assert_eq!(conj.real().to_f64(), 3.0);
1253 assert_eq!(conj.imag().to_f64(), -4.0);
1254 }
1255
1256 #[test]
1257 fn testprecision_builder() {
1258 let x = ArbitraryPrecisionBuilder::new()
1259 .decimalprecision(50)
1260 .rounding(RoundingMode::Nearest)
1261 .build_float();
1262
1263 assert!(x.decimalprecision() >= 49); }
1265
1266 #[test]
1267 fn test_constants() {
1268 let pi = utils::pi(256).expect("Operation failed");
1269 let pi_str = pi.to_string();
1270 assert!(pi_str.starts_with("3.14159265358979"));
1271
1272 let e = utils::e(256).expect("Operation failed");
1273 let e_str = e.to_string();
1274 assert!(e_str.starts_with("2.71828182845904"));
1275 }
1276
1277 #[test]
1278 fn test_prime_checking() {
1279 let prime = ArbitraryInt::from_i64(97);
1280 assert!(prime.is_probably_prime(20));
1281
1282 let composite = ArbitraryInt::from_i64(98);
1283 assert!(!composite.is_probably_prime(20));
1284 }
1285
1286 #[test]
1287 fn test_gcd_lcm() {
1288 let a = ArbitraryInt::from_i64(48);
1289 let b = ArbitraryInt::from_i64(18);
1290
1291 let gcd = a.gcd(&b);
1292 assert_eq!(gcd.to_string(), "6");
1293
1294 let lcm = a.lcm(&b);
1295 assert_eq!(lcm.to_string(), "144");
1296 }
1297
1298 #[test]
1299 fn test_transcendental_functions() {
1300 let x = ArbitraryFloat::from_f64_withprecision(0.5, 128).expect("Operation failed");
1301
1302 let sin_x = x.sin();
1303 let cos_x = x.cos();
1304 let identity = sin_x.clone() * sin_x + cos_x.clone() * cos_x;
1305
1306 assert!((identity.to_f64() - 1.0).abs() < 1e-15);
1308
1309 let ln_x = x.ln().expect("Operation failed");
1310 let exp_ln_x = ln_x.exp();
1311 assert!((exp_ln_x.to_f64() - 0.5).abs() < 1e-15);
1312 }
1313
1314 #[test]
1315 fn testerror_handling() {
1316 let zero = ArbitraryRational::new();
1318 assert!(zero.recip().is_err());
1319
1320 let neg = ArbitraryFloat::from_f64(-1.0);
1322 assert!(neg.sqrt().is_err());
1323
1324 assert!(neg.ln().is_err());
1326
1327 let out_of_range = ArbitraryFloat::from_f64(2.0);
1329 assert!(out_of_range.asin().is_err());
1330 }
1331}