Skip to main content

scheme_rs/
num.rs

1//! Scheme numerical tower.
2//!
3//! For more detailed information about the scheme numerical tower from the
4//! language perspective, please [refer to the language reference](www.scheme.rs/Language Reference/#numeric-tower).
5//!
6//! The core numeric value for scheme-rs is [`Number`], which is a reference
7//! counted numeric value that can be any of the following types:
8//!
9//! - **Fixed num**: [a signed 64-bit integer](std::i64),
10//! - **Big num**: an [arbitrary-precision integer](malachite::Integer),
11//! - **Rational**: an
12//!   [arbitrary-precision rational](malachite::rational::Rational),
13//! - **Real**: a [64-bit IEEE float point number](std::f64), or
14//! - **Complex**: a pair of two of any of the previous value types.
15//!
16//! `Number` implements all of the expected Rust operators, including [`Neg`],
17//! [`Add`], [`Mul`], [`Sub`], [`Div`], [`Rem`], [`PartialEq`], and
18//! [`PartialOrd`], while also inheriting all of the issues of IEEE floating
19//! point numbers such as [NaN not being equal to itself](https://en.wikipedia.org/wiki/NaN#Comparison_with_NaN)
20//! and therefore being unable to implement [`Eq`]. To get around these issues
21//! in cases where it is desirable to have strict equivalent for `Number` types,
22//! such as when `Number` is a key in a hash table, the [`eqv`](Number::eqv)
23//! method is provided, for which NaNs are treated as equivalent.
24
25use crate::{
26    exceptions::Exception,
27    gc::Trace,
28    ports::{BufferMode, Port, Transcoder},
29    registry::bridge,
30    strings::WideString,
31    syntax::{Span, lex::Lexer},
32    value::{Value, ValueType},
33};
34use core::f64;
35use malachite::{
36    Integer,
37    base::{
38        num::{
39            arithmetic::traits::{FloorSqrt, Parity, Pow},
40            conversion::traits::{ConvertibleFrom, RoundingFrom, WrappingFrom},
41        },
42        rounding_modes::RoundingMode,
43    },
44    rational::Rational,
45};
46use num::ToPrimitive;
47use scheme_rs_macros::{maybe_async, maybe_await};
48use std::{
49    cmp::Ordering,
50    fmt,
51    hash::Hash,
52    io::Cursor,
53    ops::{Add, Div, Mul, Neg, Rem, Sub},
54    sync::Arc,
55};
56
57#[repr(align(16))]
58pub(crate) enum NumberInner {
59    Simple(SimpleNumber),
60    Complex(ComplexNumber),
61}
62
63/// Scheme numeric type.
64#[derive(Clone, Trace)]
65pub struct Number(pub(crate) Arc<NumberInner>);
66
67macro_rules! number_dispatch_method {
68    ( $func:ident ) => {
69        pub fn $func(&self) -> Self {
70            match self.0.as_ref() {
71                NumberInner::Simple(simple) => Number::from(simple.$func()),
72                NumberInner::Complex(complex) => Number::from(complex.$func()),
73            }
74        }
75    };
76}
77
78impl Number {
79    pub fn as_simple(&self) -> Option<&SimpleNumber> {
80        match self.0.as_ref() {
81            NumberInner::Simple(simple) => Some(simple),
82            NumberInner::Complex(_) => None,
83        }
84    }
85
86    pub fn as_complex(&self) -> Option<&ComplexNumber> {
87        match self.0.as_ref() {
88            NumberInner::Complex(complex) => Some(complex),
89            NumberInner::Simple(_) => None,
90        }
91    }
92
93    pub fn is_zero(&self) -> bool {
94        match self.0.as_ref() {
95            NumberInner::Simple(simple) => simple.is_zero(),
96            NumberInner::Complex(complex) => complex.re.is_zero() && complex.im.is_zero(),
97        }
98    }
99
100    pub fn is_integer(&self) -> bool {
101        match self.0.as_ref() {
102            NumberInner::Simple(simple) => simple.is_integer(),
103            NumberInner::Complex(complex) => {
104                complex.im.is_exact() && complex.im.is_zero() && complex.re.is_integer()
105            }
106        }
107    }
108
109    pub fn is_rational(&self) -> bool {
110        match self.0.as_ref() {
111            NumberInner::Simple(simple) => simple.is_rational(),
112            NumberInner::Complex(complex) => {
113                complex.im.is_exact() && complex.im.is_zero() && complex.re.is_rational()
114            }
115        }
116    }
117
118    pub fn is_real(&self) -> bool {
119        match self.0.as_ref() {
120            NumberInner::Simple(_) => true,
121            NumberInner::Complex(complex) => complex.im.is_exact() && complex.im.is_zero(),
122        }
123    }
124
125    pub fn is_integer_valued(&self) -> bool {
126        match self.0.as_ref() {
127            NumberInner::Simple(simple) => simple.is_integer(),
128            NumberInner::Complex(complex) => complex.im.is_zero() && complex.re.is_integer(),
129        }
130    }
131
132    pub fn is_rational_valued(&self) -> bool {
133        match self.0.as_ref() {
134            NumberInner::Simple(simple) => simple.is_rational(),
135            NumberInner::Complex(complex) => complex.im.is_zero() && complex.re.is_rational(),
136        }
137    }
138
139    pub fn is_real_valued(&self) -> bool {
140        match self.0.as_ref() {
141            NumberInner::Simple(_) => true,
142            NumberInner::Complex(complex) => complex.im.is_zero(),
143        }
144    }
145
146    /// All numbers are complex!
147    pub fn is_complex(&self) -> bool {
148        true
149    }
150
151    pub fn is_exact(&self) -> bool {
152        match self.0.as_ref() {
153            NumberInner::Simple(simple) => simple.is_exact(),
154            NumberInner::Complex(complex) => complex.im.is_exact() && complex.re.is_exact(),
155        }
156    }
157
158    pub fn is_inexact(&self) -> bool {
159        match self.0.as_ref() {
160            NumberInner::Simple(simple) => !simple.is_exact(),
161            NumberInner::Complex(complex) => !complex.im.is_exact() || !complex.re.is_exact(),
162        }
163    }
164
165    pub fn inexact(self) -> Number {
166        match self.0.as_ref() {
167            NumberInner::Simple(simple) => Number::from(simple.inexact()),
168            NumberInner::Complex(complex) => Number::from(complex.inexact()),
169        }
170    }
171
172    pub fn exact(self) -> Number {
173        match self.0.as_ref() {
174            NumberInner::Simple(simple) => Number::from(simple.exact()),
175            NumberInner::Complex(complex) => Number::from(complex.exact()),
176        }
177    }
178
179    pub fn eqv(&self, rhs: &Self) -> bool {
180        match (self.0.as_ref(), rhs.0.as_ref()) {
181            (NumberInner::Simple(lhs), NumberInner::Simple(rhs)) => lhs.eqv(rhs),
182            (NumberInner::Complex(lhs), NumberInner::Simple(rhs))
183                if lhs.im.is_zero() && lhs.im.is_exact() == rhs.is_exact() =>
184            {
185                lhs.re.eqv(rhs)
186            }
187            (NumberInner::Simple(lhs), NumberInner::Complex(rhs))
188                if rhs.im.is_zero() && rhs.im.is_exact() == lhs.is_exact() =>
189            {
190                lhs.eqv(&rhs.re)
191            }
192            (NumberInner::Complex(lhs), NumberInner::Complex(rhs)) => {
193                lhs.re.eqv(&rhs.re) && lhs.im.eqv(&rhs.im)
194            }
195            _ => false,
196        }
197    }
198
199    pub fn pow(&self, rhs: &Number) -> Number {
200        match (self.0.as_ref(), rhs.0.as_ref()) {
201            (NumberInner::Simple(base), NumberInner::Simple(exp)) => Number::from(base.pow(exp)),
202            (NumberInner::Simple(base), NumberInner::Complex(exp)) => {
203                Number::from(ComplexNumber::new(base.clone(), SimpleNumber::zero()).powc(exp))
204            }
205            (NumberInner::Complex(base), NumberInner::Simple(exp)) => {
206                Number::from(base.powc(&ComplexNumber::new(exp.clone(), SimpleNumber::zero())))
207            }
208            (NumberInner::Complex(base), NumberInner::Complex(exp)) => Number::from(base.powc(exp)),
209        }
210    }
211
212    number_dispatch_method!(exp);
213    number_dispatch_method!(ln);
214    number_dispatch_method!(sqrt);
215    number_dispatch_method!(sin);
216    number_dispatch_method!(cos);
217    number_dispatch_method!(tan);
218    // number_dispatch_method!(sinh);
219    // number_dispatch_method!(cosh);
220    // number_dispatch_method!(tanh);
221    number_dispatch_method!(asin);
222    number_dispatch_method!(acos);
223    number_dispatch_method!(atan);
224}
225
226impl From<NumberInner> for Number {
227    fn from(value: NumberInner) -> Self {
228        Self(Arc::new(value))
229    }
230}
231
232impl<T> From<T> for Number
233where
234    SimpleNumber: From<T>,
235{
236    fn from(value: T) -> Self {
237        Self(Arc::new(NumberInner::Simple(SimpleNumber::from(value))))
238    }
239}
240
241macro_rules! impl_simple_number_int_conversion_for_num {
242    ($ty:ty) => {
243        impl TryFrom<&Number> for $ty {
244            type Error = Exception;
245
246            fn try_from(num: &Number) -> Result<$ty, Self::Error> {
247                match num.0.as_ref() {
248                    NumberInner::Simple(simple) => simple.try_into(),
249                    NumberInner::Complex(complex)
250                        if complex.im.is_exact() && complex.im.is_zero() =>
251                    {
252                        <$ty as TryFrom<&SimpleNumber>>::try_from(&complex.re)
253                    }
254                    _ => Err(Exception::conversion_error(stringify!($ty), "complex")),
255                }
256            }
257        }
258
259        impl TryFrom<Number> for $ty {
260            type Error = Exception;
261
262            fn try_from(num: Number) -> Result<$ty, Self::Error> {
263                <$ty as TryFrom<&Number>>::try_from(&num)
264            }
265        }
266
267        impl From<&Number> for Option<$ty> {
268            fn from(num: &Number) -> Option<$ty> {
269                match num.0.as_ref() {
270                    NumberInner::Simple(simple) => simple.into(),
271                    NumberInner::Complex(complex)
272                        if complex.im.is_exact() && complex.im.is_zero() =>
273                    {
274                        <Option<$ty> as From<&SimpleNumber>>::from(&complex.re)
275                    }
276                    _ => None,
277                }
278            }
279        }
280
281        impl From<Number> for Option<$ty> {
282            fn from(num: Number) -> Option<$ty> {
283                Self::from(&num)
284            }
285        }
286    };
287}
288
289impl_simple_number_int_conversion_for_num!(u8);
290impl_simple_number_int_conversion_for_num!(u16);
291impl_simple_number_int_conversion_for_num!(u32);
292impl_simple_number_int_conversion_for_num!(u64);
293impl_simple_number_int_conversion_for_num!(u128);
294impl_simple_number_int_conversion_for_num!(usize);
295impl_simple_number_int_conversion_for_num!(i8);
296impl_simple_number_int_conversion_for_num!(i16);
297impl_simple_number_int_conversion_for_num!(i32);
298impl_simple_number_int_conversion_for_num!(i64);
299impl_simple_number_int_conversion_for_num!(i128);
300impl_simple_number_int_conversion_for_num!(isize);
301impl_simple_number_int_conversion_for_num!(Integer);
302
303/// Scheme simple numeric type (i.e. numbers that satisfy `real?`)
304#[derive(Clone)]
305#[repr(align(16))]
306pub enum SimpleNumber {
307    FixedInteger(i64),
308    BigInteger(Integer),
309    Rational(Rational),
310    Real(f64),
311}
312
313impl SimpleNumber {
314    pub fn zero() -> Self {
315        Self::FixedInteger(0)
316    }
317
318    pub fn one() -> Self {
319        Self::FixedInteger(1)
320    }
321
322    pub fn infinity() -> Self {
323        Self::Real(f64::INFINITY)
324    }
325
326    pub fn neg_infinity() -> Self {
327        Self::Real(f64::NEG_INFINITY)
328    }
329
330    pub fn is_zero(&self) -> bool {
331        match self {
332            SimpleNumber::FixedInteger(i) => *i == 0,
333            SimpleNumber::BigInteger(i) => *i == 0,
334            SimpleNumber::Rational(r) => *r == 0,
335            SimpleNumber::Real(r) => *r == 0.0,
336        }
337    }
338
339    pub fn is_one(&self) -> bool {
340        match self {
341            SimpleNumber::FixedInteger(i) => *i == 1,
342            SimpleNumber::BigInteger(i) => *i == 1,
343            SimpleNumber::Rational(r) => *r == 1,
344            SimpleNumber::Real(r) => *r == 1.0,
345        }
346    }
347
348    pub fn is_neg_one(&self) -> bool {
349        match self {
350            SimpleNumber::FixedInteger(i) => *i == -1,
351            SimpleNumber::BigInteger(i) => *i == -1,
352            SimpleNumber::Rational(r) => *r == -1,
353            SimpleNumber::Real(r) => *r == -1.0,
354        }
355    }
356
357    pub fn is_exact(&self) -> bool {
358        matches!(
359            self,
360            Self::FixedInteger(_) | Self::BigInteger(_) | Self::Rational(_)
361        )
362    }
363
364    pub fn to_string(&self, radix: u32, precision: Option<usize>) -> Option<String> {
365        match radix {
366            2 => match self {
367                SimpleNumber::FixedInteger(i) => Some(format!("{i:b}")),
368                SimpleNumber::BigInteger(i) => Some(format!("{i:b}")),
369                SimpleNumber::Rational(r) => {
370                    let (n, d) = r.numerator_and_denominator_ref();
371                    if *r < 0 {
372                        Some(format!("-{n:b}/{d:b}"))
373                    } else {
374                        Some(format!("{n:b}/{d:b}"))
375                    }
376                }
377                SimpleNumber::Real(_) => None,
378            },
379            8 => match self {
380                SimpleNumber::FixedInteger(i) => Some(format!("{i:o}")),
381                SimpleNumber::BigInteger(i) => Some(format!("{i:o}")),
382                SimpleNumber::Rational(r) => {
383                    let (n, d) = r.numerator_and_denominator_ref();
384                    if *r < 0 {
385                        Some(format!("-{n:o}/{d:o}"))
386                    } else {
387                        Some(format!("{n:o}/{d:o}"))
388                    }
389                }
390                SimpleNumber::Real(_) => None,
391            },
392            10 => match self {
393                SimpleNumber::FixedInteger(i) => Some(format!("{i}")),
394                SimpleNumber::BigInteger(i) => Some(format!("{i}")),
395                SimpleNumber::Rational(r) => Some(format!("{r}")),
396                SimpleNumber::Real(r) => {
397                    if let Some(precision) = precision {
398                        Some(format!("{r:.precision$}"))
399                    } else {
400                        Some(format!("{r}"))
401                    }
402                }
403            },
404            16 => match self {
405                SimpleNumber::FixedInteger(i) => Some(format!("{i:X}")),
406                SimpleNumber::BigInteger(i) => Some(format!("{i:X}")),
407                SimpleNumber::Rational(r) => {
408                    let (n, d) = r.numerator_and_denominator_ref();
409                    if *r < 0 {
410                        Some(format!("-{n:X}/{d:X}"))
411                    } else {
412                        Some(format!("{n:X}/{d:X}"))
413                    }
414                }
415                SimpleNumber::Real(_) => None,
416            },
417            _ => None,
418        }
419    }
420
421    pub fn is_nan(&self) -> bool {
422        if let Self::Real(real) = self {
423            real.is_nan()
424        } else {
425            false
426        }
427    }
428
429    pub fn is_finite(&self) -> bool {
430        matches!(self, Self::Real(r) if r.is_finite())
431    }
432
433    pub fn is_infinite(&self) -> bool {
434        if let Self::Real(real) = self {
435            real.is_infinite()
436        } else {
437            false
438        }
439    }
440
441    pub fn is_negative(&self) -> bool {
442        match self {
443            SimpleNumber::FixedInteger(i) => i.is_negative(),
444            SimpleNumber::BigInteger(i) => *i < 0i32,
445            SimpleNumber::Rational(r) => *r < 0i32,
446            SimpleNumber::Real(r) => r.is_sign_negative(),
447        }
448    }
449
450    pub fn is_positive(&self) -> bool {
451        match self {
452            SimpleNumber::FixedInteger(i) => i.is_positive(),
453            SimpleNumber::BigInteger(i) => *i >= 0i32,
454            SimpleNumber::Rational(r) => *r >= 0i32,
455            SimpleNumber::Real(r) => r.is_sign_positive(),
456        }
457    }
458
459    pub fn is_integer(&self) -> bool {
460        match self {
461            SimpleNumber::FixedInteger(_) | SimpleNumber::BigInteger(_) => true,
462            SimpleNumber::Rational(r) => *r.denominator_ref() == 1u32,
463            SimpleNumber::Real(r) => r.fract() == 0.0,
464        }
465    }
466
467    pub fn is_rational(&self) -> bool {
468        match self {
469            SimpleNumber::FixedInteger(_)
470            | SimpleNumber::BigInteger(_)
471            | SimpleNumber::Rational(_) => true,
472            SimpleNumber::Real(r) => !r.is_infinite() && !r.is_nan(),
473        }
474    }
475
476    pub fn to_integer(&self, rounding_mode: RoundingMode) -> Self {
477        match self {
478            Self::FixedInteger(i) => Self::FixedInteger(*i),
479            Self::BigInteger(i) => Self::BigInteger(i.clone()),
480            Self::Rational(r) => Self::BigInteger(Integer::rounding_from(r, rounding_mode).0),
481            Self::Real(r) if r.is_nan() || r.is_infinite() => Self::Real(*r),
482            Self::Real(r) => Self::BigInteger(Integer::rounding_from(*r, rounding_mode).0),
483        }
484    }
485
486    pub fn inexact(&self) -> Self {
487        match self {
488            Self::FixedInteger(i) => Self::Real(*i as f64),
489            Self::BigInteger(i) => Self::Real(f64::rounding_from(i, RoundingMode::Nearest).0),
490            Self::Rational(r) => Self::Real(f64::rounding_from(r, RoundingMode::Nearest).0),
491            Self::Real(r) => Self::Real(*r),
492        }
493    }
494
495    pub fn exact(&self) -> Self {
496        match self {
497            // We can do better than this, but it'll do for now
498            Self::Real(r) if !r.is_nan() && !r.is_infinite() && r.fract() == 0.0 => {
499                Self::BigInteger(Integer::rounding_from(*r, RoundingMode::Nearest).0)
500            }
501            Self::Real(r) => match Rational::try_from_float_simplest(*r) {
502                Ok(r) => Self::Rational(r),
503                _ => self.clone(),
504            },
505            num => num.clone(),
506        }
507    }
508
509    pub fn abs(&self) -> Self {
510        if *self < SimpleNumber::zero() {
511            -self
512        } else {
513            self.clone()
514        }
515    }
516
517    pub fn powi(&self, p: i32) -> Self {
518        match self {
519            SimpleNumber::FixedInteger(i) => i.checked_pow(p as u32).map_or_else(
520                || SimpleNumber::BigInteger(Integer::from(*i).pow(p as u64)),
521                SimpleNumber::FixedInteger,
522            ),
523            SimpleNumber::BigInteger(i) => SimpleNumber::BigInteger(i.pow(p as u64)),
524            SimpleNumber::Rational(r) => SimpleNumber::Rational(r.pow(p as u64)),
525            SimpleNumber::Real(r) => SimpleNumber::Real(r.powi(p)),
526        }
527    }
528
529    pub fn div_euclid(&self, rhs: &Self) -> Self {
530        if rhs.is_positive() {
531            (self / rhs).to_integer(RoundingMode::Floor)
532        } else {
533            (self / rhs).to_integer(RoundingMode::Ceiling)
534        }
535    }
536
537    pub fn pow(&self, p: &SimpleNumber) -> Self {
538        if self.is_zero() {
539            if p.is_zero() {
540                if self.is_exact() && p.is_exact() {
541                    return Self::from(1);
542                } else {
543                    return Self::from(1.0);
544                }
545            } else if p.is_positive() {
546                if self.is_exact() && p.is_exact() {
547                    return Self::from(0);
548                } else {
549                    return Self::from(0.0);
550                }
551            } else {
552                return Self::infinity();
553            }
554        }
555        match (self, p) {
556            (SimpleNumber::FixedInteger(l), SimpleNumber::FixedInteger(r)) if *r >= 0 => {
557                SimpleNumber::from(Integer::from(*l).pow(*r as u64))
558            }
559            (SimpleNumber::FixedInteger(l), SimpleNumber::FixedInteger(r)) if *r < 0 => {
560                SimpleNumber::from(Rational::from_integers(
561                    Integer::from(1),
562                    Integer::from(*l).pow(-*r as u64),
563                ))
564            }
565            (SimpleNumber::FixedInteger(l), SimpleNumber::BigInteger(i)) if *i >= 0 => {
566                let exp: Option<u64> = i.try_into().ok();
567                if let Some(exp) = exp {
568                    SimpleNumber::from(Integer::from(*l).pow(exp))
569                } else {
570                    SimpleNumber::infinity()
571                }
572            }
573            (SimpleNumber::FixedInteger(l), SimpleNumber::BigInteger(i)) if *i < 0 => {
574                let exp: Option<u64> = (&(-i)).try_into().ok();
575                if let Some(exp) = exp {
576                    SimpleNumber::from(Rational::from_integers(
577                        Integer::from(1),
578                        Integer::from(*l).pow(exp),
579                    ))
580                } else {
581                    SimpleNumber::zero()
582                }
583            }
584            (SimpleNumber::BigInteger(l), SimpleNumber::FixedInteger(r)) if *r >= 0 => {
585                SimpleNumber::from(l.pow(*r as u64))
586            }
587            (SimpleNumber::BigInteger(l), SimpleNumber::FixedInteger(r)) if *r < 0 => {
588                SimpleNumber::from(Rational::from_integers(Integer::from(1), l.pow(-*r as u64)))
589            }
590            (SimpleNumber::BigInteger(l), SimpleNumber::BigInteger(i)) if *i >= 0 => {
591                let exp: Option<u64> = i.try_into().ok();
592                if let Some(exp) = exp {
593                    SimpleNumber::from(l.pow(exp))
594                } else {
595                    SimpleNumber::infinity()
596                }
597            }
598            (SimpleNumber::BigInteger(l), SimpleNumber::BigInteger(i)) if *i < 0 => {
599                let exp: Option<u64> = (&(-i)).try_into().ok();
600                if let Some(exp) = exp {
601                    SimpleNumber::from(Rational::from_integers(Integer::from(1), l.pow(exp)))
602                } else {
603                    SimpleNumber::zero()
604                }
605            }
606            (SimpleNumber::Rational(r), SimpleNumber::FixedInteger(exp)) if *exp >= 0 => {
607                SimpleNumber::from(r.pow(*exp as u64))
608            }
609            (SimpleNumber::Rational(r), SimpleNumber::FixedInteger(exp)) if *exp < 0 => {
610                SimpleNumber::from((Rational::from(1) / r).pow(-exp as u64))
611            }
612            (l, r) => {
613                let l = l.to_f64();
614                let r = r.to_f64();
615                SimpleNumber::from(l.powf(r))
616            }
617        }
618    }
619
620    pub fn sqrt(&self) -> Self {
621        match self {
622            SimpleNumber::FixedInteger(i) => SimpleNumber::Real((*i as f64).sqrt()),
623            SimpleNumber::BigInteger(i) => {
624                SimpleNumber::Real(f64::rounding_from(i, RoundingMode::Nearest).0.sqrt())
625            }
626            SimpleNumber::Rational(r) => {
627                SimpleNumber::Real(f64::rounding_from(r, RoundingMode::Nearest).0.sqrt())
628            }
629            SimpleNumber::Real(r) => SimpleNumber::Real(r.sqrt()),
630        }
631    }
632
633    // Numbers are only equivalent if they're the same exactness
634    // Two NaNs are also treated as equivalent
635    pub fn eqv(&self, rhs: &Self) -> bool {
636        (self.is_nan() && rhs.is_nan()) || (self.is_exact() == rhs.is_exact() && self == rhs)
637    }
638
639    pub fn to_f64(&self) -> f64 {
640        match self {
641            Self::FixedInteger(i) => *i as f64,
642            Self::BigInteger(i) => f64::rounding_from(i, RoundingMode::Nearest).0,
643            Self::Rational(r) => f64::rounding_from(r, RoundingMode::Nearest).0,
644            Self::Real(r) => *r,
645        }
646    }
647
648    pub fn exp(&self) -> Self {
649        Self::Real(self.to_f64().exp())
650    }
651
652    pub fn ln(&self) -> Self {
653        Self::Real(self.to_f64().ln())
654    }
655
656    pub fn sin(&self) -> Self {
657        Self::Real(self.to_f64().sin())
658    }
659
660    pub fn cos(&self) -> Self {
661        Self::Real(self.to_f64().cos())
662    }
663
664    pub fn tan(&self) -> Self {
665        Self::Real(self.to_f64().tan())
666    }
667
668    pub fn sinh(&self) -> Self {
669        Self::Real(self.to_f64().sinh())
670    }
671
672    pub fn cosh(&self) -> Self {
673        Self::Real(self.to_f64().cosh())
674    }
675
676    pub fn tanh(&self) -> Self {
677        Self::Real(self.to_f64().tanh())
678    }
679
680    pub fn asin(&self) -> Self {
681        Self::Real(self.to_f64().asin())
682    }
683
684    pub fn acos(&self) -> Self {
685        Self::Real(self.to_f64().acos())
686    }
687
688    pub fn atan(&self) -> Self {
689        Self::Real(self.to_f64().atan())
690    }
691
692    pub fn atan2(&self, num2: &Self) -> Self {
693        Self::Real(self.to_f64().atan2(num2.to_f64()))
694    }
695}
696
697impl From<&Number> for Option<SimpleNumber> {
698    fn from(value: &Number) -> Self {
699        match value.0.as_ref() {
700            NumberInner::Simple(simple) => Some(simple.clone()),
701            NumberInner::Complex(complex) if complex.im.is_exact() && complex.im.is_zero() => {
702                Some(complex.re.clone())
703            }
704            _ => None,
705        }
706    }
707}
708
709impl From<Number> for Option<SimpleNumber> {
710    fn from(value: Number) -> Self {
711        Self::from(&value)
712    }
713}
714
715impl TryFrom<&Number> for SimpleNumber {
716    type Error = Exception;
717
718    fn try_from(value: &Number) -> Result<Self, Self::Error> {
719        <Option<SimpleNumber> as From<&Number>>::from(value)
720            .ok_or_else(|| Exception::type_error("real?", "complex?"))
721    }
722}
723
724impl TryFrom<Number> for SimpleNumber {
725    type Error = Exception;
726
727    fn try_from(value: Number) -> Result<Self, Self::Error> {
728        <Option<SimpleNumber> as From<Number>>::from(value)
729            .ok_or_else(|| Exception::type_error("real?", "complex?"))
730    }
731}
732
733macro_rules! impl_from_int {
734    ($ty:ty) => {
735        impl From<$ty> for SimpleNumber {
736            fn from(i: $ty) -> Self {
737                SimpleNumber::FixedInteger(i as i64)
738            }
739        }
740    };
741}
742
743impl_from_int!(i8);
744impl_from_int!(i16);
745impl_from_int!(i32);
746impl_from_int!(i64);
747impl_from_int!(u8);
748impl_from_int!(u16);
749impl_from_int!(u32);
750impl_from_int!(u64);
751
752macro_rules! impl_from_large_int {
753    ($ty:ty) => {
754        impl From<$ty> for SimpleNumber {
755            fn from(u: $ty) -> Self {
756                match u.try_into() {
757                    Ok(i) => SimpleNumber::FixedInteger(i),
758                    Err(_) => SimpleNumber::BigInteger(Integer::from(u)),
759                }
760            }
761        }
762    };
763}
764
765impl_from_large_int!(i128);
766impl_from_large_int!(isize);
767impl_from_large_int!(u128);
768impl_from_large_int!(usize);
769
770impl From<Integer> for SimpleNumber {
771    fn from(i: Integer) -> Self {
772        Self::BigInteger(i)
773    }
774}
775
776impl From<Rational> for SimpleNumber {
777    fn from(r: Rational) -> Self {
778        Self::Rational(r)
779    }
780}
781
782impl From<f64> for SimpleNumber {
783    fn from(r: f64) -> Self {
784        Self::Real(r)
785    }
786}
787
788impl From<ComplexNumber> for Number {
789    fn from(complex: ComplexNumber) -> Self {
790        Self(Arc::new(NumberInner::Complex(complex)))
791    }
792}
793
794macro_rules! number_try_into_impl_integer {
795    ($ty:tt) => {
796        impl TryFrom<&SimpleNumber> for $ty {
797            type Error = Exception;
798
799            fn try_from(num: &SimpleNumber) -> Result<$ty, Self::Error> {
800                match num {
801                    SimpleNumber::FixedInteger(i) => {
802                        // Since FixedInteger is i64, we can just check for
803                        // greater than size_of::<u32>() to know if we should just
804                        // cast the value to the type or check for the right size.
805                        if size_of::<$ty>() > size_of::<u32>() {
806                            Ok(*i as $ty)
807                        } else if *i <= $ty::MAX as i64 && *i >= $ty::MIN as i64 {
808                            Ok(*i as $ty)
809                        } else {
810                            Err(Exception::not_representable(
811                                &format!("{i}"),
812                                stringify!($ty),
813                            ))
814                        }
815                    }
816                    SimpleNumber::BigInteger(bigint) => $ty::convertible_from(bigint)
817                        .then(|| $ty::wrapping_from(bigint))
818                        .ok_or_else(|| {
819                            Exception::not_representable(&format!("{bigint}"), stringify!($ty))
820                        }),
821                    SimpleNumber::Rational(_) => {
822                        Err(Exception::conversion_error(stringify!($ty), "rational"))
823                    }
824                    SimpleNumber::Real(_) => {
825                        Err(Exception::conversion_error(stringify!($ty), "real"))
826                    }
827                }
828            }
829        }
830
831        impl TryFrom<SimpleNumber> for $ty {
832            type Error = Exception;
833
834            fn try_from(num: SimpleNumber) -> Result<$ty, Self::Error> {
835                $ty::try_from(&num)
836            }
837        }
838
839        impl From<&SimpleNumber> for Option<$ty> {
840            fn from(num: &SimpleNumber) -> Option<$ty> {
841                match num {
842                    SimpleNumber::FixedInteger(i) => {
843                        if size_of::<$ty>() > size_of::<u32>() {
844                            Some(*i as $ty)
845                        } else if *i <= $ty::MAX as i64 && *i >= $ty::MIN as i64 {
846                            Some(*i as $ty)
847                        } else {
848                            None
849                        }
850                    }
851                    SimpleNumber::BigInteger(bigint) => {
852                        $ty::convertible_from(bigint).then(|| $ty::wrapping_from(bigint))
853                    }
854                    _ => None,
855                }
856            }
857        }
858
859        impl From<SimpleNumber> for Option<$ty> {
860            fn from(num: SimpleNumber) -> Option<$ty> {
861                Self::from(&num)
862            }
863        }
864    };
865}
866
867number_try_into_impl_integer!(u8);
868number_try_into_impl_integer!(u16);
869number_try_into_impl_integer!(u32);
870number_try_into_impl_integer!(u64);
871number_try_into_impl_integer!(u128);
872number_try_into_impl_integer!(usize);
873number_try_into_impl_integer!(i8);
874number_try_into_impl_integer!(i16);
875number_try_into_impl_integer!(i32);
876number_try_into_impl_integer!(i64);
877number_try_into_impl_integer!(i128);
878number_try_into_impl_integer!(isize);
879
880impl TryFrom<&SimpleNumber> for Integer {
881    type Error = Exception;
882
883    fn try_from(num: &SimpleNumber) -> Result<Integer, Self::Error> {
884        match num {
885            SimpleNumber::FixedInteger(i) => Ok(Integer::from(*i)),
886            SimpleNumber::BigInteger(i) => Ok(i.clone()),
887            SimpleNumber::Rational(r) if *r.denominator_ref() == 1u32 => {
888                Ok(Integer::from(r.to_numerator()))
889            }
890            SimpleNumber::Rational(_) => Err(Exception::conversion_error("integer", "rational")),
891            SimpleNumber::Real(r) if !r.is_nan() && !r.is_infinite() && r.fract() == 0.0 => {
892                Ok(Integer::rounding_from(*r, RoundingMode::Nearest).0)
893            }
894            SimpleNumber::Real(_) => Err(Exception::conversion_error("integer", "real")),
895        }
896    }
897}
898
899impl TryFrom<SimpleNumber> for Integer {
900    type Error = Exception;
901
902    fn try_from(num: SimpleNumber) -> Result<Integer, Self::Error> {
903        Integer::try_from(&num)
904    }
905}
906
907impl From<&SimpleNumber> for Option<Integer> {
908    fn from(num: &SimpleNumber) -> Option<Integer> {
909        match num {
910            SimpleNumber::FixedInteger(i) => Some(Integer::from(*i)),
911            SimpleNumber::BigInteger(i) => Some(i.clone()),
912            SimpleNumber::Rational(r) if *r.denominator_ref() == 1u32 => {
913                Some(Integer::from(r.to_numerator()))
914            }
915            SimpleNumber::Rational(_) => None,
916            SimpleNumber::Real(r) if !r.is_nan() && !r.is_infinite() && r.fract() == 0.0 => {
917                Some(Integer::rounding_from(*r, RoundingMode::Nearest).0)
918            }
919            SimpleNumber::Real(_) => None,
920        }
921    }
922}
923
924impl From<SimpleNumber> for Option<Integer> {
925    fn from(num: SimpleNumber) -> Option<Integer> {
926        Self::from(&num)
927    }
928}
929
930impl TryFrom<&SimpleNumber> for f64 {
931    type Error = Exception;
932
933    fn try_from(num: &SimpleNumber) -> Result<f64, Self::Error> {
934        match num {
935            SimpleNumber::FixedInteger(i) => Ok(*i as f64),
936            SimpleNumber::Real(r) => Ok(*r),
937            SimpleNumber::Rational(r) => {
938                if let Some((float, _, _)) =
939                    r.sci_mantissa_and_exponent_round_ref(RoundingMode::Nearest)
940                {
941                    Ok(float)
942                } else {
943                    Err(Exception::not_representable(&format!("{r}"), "f64"))
944                }
945            }
946            SimpleNumber::BigInteger(_) => Err(Exception::conversion_error("f64", "integer")),
947        }
948    }
949}
950
951impl TryFrom<SimpleNumber> for f64 {
952    type Error = Exception;
953
954    fn try_from(num: SimpleNumber) -> Result<f64, Self::Error> {
955        f64::try_from(&num)
956    }
957}
958
959impl From<&SimpleNumber> for Option<f64> {
960    fn from(num: &SimpleNumber) -> Option<f64> {
961        match num {
962            SimpleNumber::FixedInteger(i) => Some(*i as f64),
963            SimpleNumber::Real(r) => Some(*r),
964            SimpleNumber::Rational(r) => r
965                .sci_mantissa_and_exponent_round_ref(RoundingMode::Nearest)
966                .map(|(float, _, _)| float),
967            SimpleNumber::BigInteger(_) => None,
968        }
969    }
970}
971
972impl From<SimpleNumber> for Option<f64> {
973    fn from(num: SimpleNumber) -> Option<f64> {
974        Self::from(&num)
975    }
976}
977
978impl TryFrom<&Number> for f64 {
979    type Error = Exception;
980
981    fn try_from(num: &Number) -> Result<f64, Self::Error> {
982        match num.0.as_ref() {
983            NumberInner::Simple(simple) => f64::try_from(simple),
984            NumberInner::Complex(complex) if !complex.im.is_exact() && complex.im.is_zero() => {
985                f64::try_from(&complex.re)
986            }
987            _ => Err(Exception::conversion_error("f64", "complex")),
988        }
989    }
990}
991
992impl TryFrom<Number> for f64 {
993    type Error = Exception;
994
995    fn try_from(num: Number) -> Result<f64, Self::Error> {
996        f64::try_from(&num)
997    }
998}
999
1000impl From<&Number> for Option<f64> {
1001    fn from(num: &Number) -> Option<f64> {
1002        match num.0.as_ref() {
1003            NumberInner::Simple(simple) => Self::from(simple),
1004            NumberInner::Complex(complex) if !complex.im.is_exact() && complex.im.is_zero() => {
1005                Self::from(&complex.re)
1006            }
1007            _ => None,
1008        }
1009    }
1010}
1011
1012impl From<Number> for Option<f64> {
1013    fn from(num: Number) -> Option<f64> {
1014        Self::from(&num)
1015    }
1016}
1017
1018impl fmt::Display for SimpleNumber {
1019    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1020        match self {
1021            Self::FixedInteger(i) => write!(f, "{i}"),
1022            Self::BigInteger(i) => write!(f, "{i}"),
1023            Self::Rational(r) => write!(f, "{r}"),
1024            Self::Real(r) if r.is_nan() => write!(f, "+nan.0"),
1025            Self::Real(r) if r.is_infinite() && r.is_sign_positive() => write!(f, "+inf.0"),
1026            Self::Real(r) if r.is_infinite() && r.is_sign_negative() => write!(f, "-inf.0"),
1027            Self::Real(r) => write!(f, "{r:?}"),
1028        }
1029    }
1030}
1031
1032impl fmt::Debug for SimpleNumber {
1033    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1034        match self {
1035            Self::FixedInteger(i) => write!(f, "{i}"),
1036            Self::BigInteger(i) => write!(f, "{i}"),
1037            Self::Rational(r) => write!(f, "{r}"),
1038            Self::Real(r) if r.is_nan() => write!(f, "+nan.0"),
1039            Self::Real(r) if r.is_infinite() && r.is_sign_positive() => write!(f, "+inf.0"),
1040            Self::Real(r) if r.is_infinite() && r.is_sign_negative() => write!(f, "-inf.0"),
1041            Self::Real(r) => write!(f, "{r:?}"),
1042        }
1043    }
1044}
1045
1046/// Hash implementation for SimpleNumber is the eqv-hash procedure from r6rs.
1047impl Hash for SimpleNumber {
1048    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
1049        match self {
1050            SimpleNumber::FixedInteger(i) => {
1051                0u8.hash(state);
1052                i.hash(state);
1053            }
1054            SimpleNumber::BigInteger(i) => {
1055                if i64::convertible_from(i) {
1056                    0u8.hash(state);
1057                    i64::wrapping_from(i).hash(state)
1058                } else {
1059                    1u8.hash(state);
1060                    i.hash(state)
1061                }
1062            }
1063            SimpleNumber::Rational(r) => {
1064                if *r.denominator_ref() == 1u32 {
1065                    let i = if *r < 0 {
1066                        -Integer::from(r.numerator_ref())
1067                    } else {
1068                        Integer::from(r.numerator_ref())
1069                    };
1070                    if i64::convertible_from(&i) {
1071                        0u8.hash(state);
1072                        i64::wrapping_from(&i).hash(state)
1073                    } else {
1074                        1u8.hash(state);
1075                        i.hash(state)
1076                    }
1077                } else {
1078                    2u8.hash(state);
1079                    r.hash(state)
1080                }
1081            }
1082            SimpleNumber::Real(r) => {
1083                3u8.hash(state);
1084                if r.is_nan() {
1085                    // Use the same bit pattern for all NaNs to mirror eqv
1086                    f64::NAN.to_bits().hash(state);
1087                } else {
1088                    r.to_bits().hash(state);
1089                }
1090            }
1091        }
1092    }
1093}
1094
1095impl PartialEq for SimpleNumber {
1096    fn eq(&self, rhs: &Self) -> bool {
1097        match (self, rhs) {
1098            (Self::FixedInteger(l), Self::FixedInteger(r)) => l == r,
1099            (Self::BigInteger(l), Self::BigInteger(r)) => l == r,
1100            (Self::Rational(l), Self::Rational(r)) => l == r,
1101            (Self::Real(l), Self::Real(r)) => l == r,
1102
1103            (Self::BigInteger(big_int), Self::FixedInteger(fixed_int))
1104            | (Self::FixedInteger(fixed_int), Self::BigInteger(big_int)) => fixed_int == big_int,
1105
1106            (Self::Rational(rational), Self::FixedInteger(fixed_int))
1107            | (Self::FixedInteger(fixed_int), Self::Rational(rational)) => fixed_int == rational,
1108
1109            (Self::BigInteger(big_int), Self::Rational(rational))
1110            | (Self::Rational(rational), Self::BigInteger(big_int)) => big_int == rational,
1111
1112            (Self::BigInteger(big_int), Self::Real(float))
1113            | (Self::Real(float), Self::BigInteger(big_int)) => float == big_int,
1114
1115            (Self::Rational(rational), Self::Real(float))
1116            | (Self::Real(float), Self::Rational(rational)) => float == rational,
1117
1118            (Self::FixedInteger(_), Self::Real(float))
1119            | (Self::Real(float), Self::FixedInteger(_))
1120                if float.fract() != 0.0 =>
1121            {
1122                false
1123            }
1124            (Self::FixedInteger(fixed_int), Self::Real(float))
1125            | (Self::Real(float), Self::FixedInteger(fixed_int)) => {
1126                float.to_i64() == Some(*fixed_int)
1127            }
1128        }
1129    }
1130}
1131
1132impl PartialOrd for SimpleNumber {
1133    fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> {
1134        match (self, rhs) {
1135            (Self::FixedInteger(l), Self::FixedInteger(r)) => l.partial_cmp(r),
1136            (Self::FixedInteger(l), Self::BigInteger(r)) => l.partial_cmp(r),
1137            (Self::FixedInteger(l), Self::Rational(r)) => l.partial_cmp(r),
1138            (Self::BigInteger(l), Self::FixedInteger(r)) => l.partial_cmp(r),
1139            (Self::BigInteger(l), Self::BigInteger(r)) => l.partial_cmp(r),
1140            (Self::BigInteger(l), Self::Rational(r)) => l.partial_cmp(r),
1141            (Self::BigInteger(l), Self::Real(r)) => l.partial_cmp(r),
1142            (Self::Rational(l), Self::FixedInteger(r)) => l.partial_cmp(r),
1143            (Self::Rational(l), Self::BigInteger(r)) => l.partial_cmp(r),
1144            (Self::Rational(l), Self::Rational(r)) => l.partial_cmp(r),
1145            (Self::Rational(l), Self::Real(r)) => l.partial_cmp(r),
1146            (Self::Real(l), Self::BigInteger(r)) => l.partial_cmp(r),
1147            (Self::Real(l), Self::Rational(r)) => l.partial_cmp(r),
1148            (Self::Real(l), Self::Real(r)) => l.partial_cmp(r),
1149            // I genuinely do not know how to properly implement these without
1150            // the use of big nums. This will work for now.
1151            (Self::FixedInteger(l), Self::Real(r)) => Integer::from(*l).partial_cmp(r),
1152            (Self::Real(l), Self::FixedInteger(r)) => l.partial_cmp(&Integer::from(*r)),
1153        }
1154    }
1155}
1156
1157impl Neg for SimpleNumber {
1158    type Output = SimpleNumber;
1159
1160    fn neg(self) -> Self {
1161        match self {
1162            Self::FixedInteger(i) => Self::FixedInteger(-i),
1163            Self::BigInteger(i) => Self::BigInteger(-i),
1164            Self::Rational(r) => Self::Rational(-r),
1165            Self::Real(r) => Self::Real(-r),
1166        }
1167    }
1168}
1169
1170impl Neg for &'_ SimpleNumber {
1171    type Output = SimpleNumber;
1172
1173    fn neg(self) -> SimpleNumber {
1174        match self {
1175            SimpleNumber::FixedInteger(i) => i.checked_neg().map_or_else(
1176                || SimpleNumber::BigInteger(-Integer::from(*i)),
1177                SimpleNumber::FixedInteger,
1178            ),
1179            SimpleNumber::BigInteger(i) => SimpleNumber::BigInteger(-i),
1180            SimpleNumber::Rational(r) => SimpleNumber::Rational(-r),
1181            SimpleNumber::Real(r) => SimpleNumber::Real(-r),
1182        }
1183    }
1184}
1185
1186macro_rules! impl_op_for_simple_numbers {
1187    ($trait:ident, $op:ident, $checked:ident) => {
1188        impl $trait for &SimpleNumber {
1189            type Output = SimpleNumber;
1190
1191            fn $op(self, rhs: &SimpleNumber) -> SimpleNumber {
1192                match (self, rhs) {
1193                    (SimpleNumber::FixedInteger(l), SimpleNumber::FixedInteger(r)) => l
1194                        .$checked(*r)
1195                        .map(SimpleNumber::FixedInteger)
1196                        .unwrap_or_else(|| {
1197                            SimpleNumber::BigInteger(Integer::from(*l).$op(Integer::from(*r)))
1198                        }),
1199                    (SimpleNumber::BigInteger(l), SimpleNumber::BigInteger(r)) => {
1200                        SimpleNumber::BigInteger(l.$op(r))
1201                    }
1202                    (SimpleNumber::Rational(l), SimpleNumber::Rational(r)) => {
1203                        SimpleNumber::Rational(l.$op(r))
1204                    }
1205                    (SimpleNumber::Real(l), SimpleNumber::Real(r)) => SimpleNumber::Real(l.$op(r)),
1206                    (SimpleNumber::BigInteger(l), SimpleNumber::FixedInteger(r)) => {
1207                        i64::convertible_from(l)
1208                            .then(|| i64::wrapping_from(l).$checked(*r))
1209                            .flatten()
1210                            .map(SimpleNumber::FixedInteger)
1211                            .unwrap_or_else(|| SimpleNumber::BigInteger(l.$op(Integer::from(*r))))
1212                    }
1213                    (SimpleNumber::FixedInteger(l), SimpleNumber::BigInteger(r)) => {
1214                        i64::convertible_from(r)
1215                            .then(|| l.$checked(i64::wrapping_from(r)))
1216                            .flatten()
1217                            .map(SimpleNumber::FixedInteger)
1218                            .unwrap_or_else(|| SimpleNumber::BigInteger(Integer::from(*l).$op(r)))
1219                    }
1220                    (SimpleNumber::Rational(l), SimpleNumber::FixedInteger(r)) => {
1221                        SimpleNumber::Rational(l.$op(Rational::from(*r)))
1222                    }
1223                    (SimpleNumber::FixedInteger(l), SimpleNumber::Rational(r)) => {
1224                        SimpleNumber::Rational(Rational::from(*l).$op(r))
1225                    }
1226
1227                    (SimpleNumber::Rational(l), SimpleNumber::BigInteger(r)) => {
1228                        SimpleNumber::Rational(l.$op(Rational::from(r)))
1229                    }
1230                    (SimpleNumber::BigInteger(l), SimpleNumber::Rational(r)) => {
1231                        SimpleNumber::Rational(Rational::from(l).$op(r))
1232                    }
1233
1234                    (SimpleNumber::BigInteger(l), SimpleNumber::Real(r)) => {
1235                        SimpleNumber::Real(f64::rounding_from(l, RoundingMode::Nearest).0.$op(*r))
1236                    }
1237                    (SimpleNumber::Real(l), SimpleNumber::BigInteger(r)) => {
1238                        SimpleNumber::Real(l.$op(f64::rounding_from(r, RoundingMode::Nearest).0))
1239                    }
1240
1241                    (SimpleNumber::Rational(l), SimpleNumber::Real(r)) => {
1242                        SimpleNumber::Real(f64::rounding_from(l, RoundingMode::Nearest).0.$op(r))
1243                    }
1244                    (SimpleNumber::Real(l), SimpleNumber::Rational(r)) => {
1245                        SimpleNumber::Real(l.$op(f64::rounding_from(r, RoundingMode::Nearest).0))
1246                    }
1247
1248                    (SimpleNumber::FixedInteger(l), SimpleNumber::Real(r)) => {
1249                        SimpleNumber::Real((*l as f64).$op(r))
1250                    }
1251
1252                    (SimpleNumber::Real(l), SimpleNumber::FixedInteger(r)) => {
1253                        SimpleNumber::Real(l.$op(*r as f64))
1254                    }
1255                }
1256            }
1257        }
1258
1259        impl $trait for SimpleNumber {
1260            type Output = SimpleNumber;
1261
1262            fn $op(self, rhs: SimpleNumber) -> SimpleNumber {
1263                (&self).$op(&rhs)
1264            }
1265        }
1266    };
1267}
1268
1269impl_op_for_simple_numbers!(Add, add, checked_add);
1270impl_op_for_simple_numbers!(Sub, sub, checked_sub);
1271impl_op_for_simple_numbers!(Mul, mul, checked_mul);
1272// impl_op_for_simple_and_complex_numbers!(Div, div, checked_div);
1273
1274impl Div for &SimpleNumber {
1275    type Output = SimpleNumber;
1276
1277    fn div(self, rhs: &SimpleNumber) -> SimpleNumber {
1278        match (self, rhs) {
1279            (SimpleNumber::FixedInteger(l), SimpleNumber::FixedInteger(r)) => {
1280                SimpleNumber::Rational(Rational::from(*l) / Rational::from(*r))
1281            }
1282            (SimpleNumber::BigInteger(l), SimpleNumber::BigInteger(r)) => {
1283                SimpleNumber::Rational(Rational::from_integers_ref(l, r))
1284            }
1285            (SimpleNumber::Rational(l), SimpleNumber::Rational(r)) => SimpleNumber::Rational(l / r),
1286            (SimpleNumber::Real(l), SimpleNumber::Real(r)) => SimpleNumber::Real(l / r),
1287
1288            (SimpleNumber::BigInteger(l), SimpleNumber::FixedInteger(r)) => {
1289                SimpleNumber::Rational(Rational::from(l) / Rational::from(*r))
1290            }
1291            (SimpleNumber::FixedInteger(l), SimpleNumber::BigInteger(r)) => {
1292                SimpleNumber::Rational(Rational::from(*l) / Rational::from(r))
1293            }
1294
1295            (SimpleNumber::Rational(l), SimpleNumber::FixedInteger(r)) => {
1296                SimpleNumber::Rational(l / Rational::from(*r))
1297            }
1298            (SimpleNumber::FixedInteger(l), SimpleNumber::Rational(r)) => {
1299                SimpleNumber::Rational(Rational::from(*l) / r)
1300            }
1301
1302            (SimpleNumber::BigInteger(l), SimpleNumber::Rational(r)) => {
1303                SimpleNumber::Rational(Rational::from(l) / r)
1304            }
1305            (SimpleNumber::Rational(l), SimpleNumber::BigInteger(r)) => {
1306                SimpleNumber::Rational(l / Rational::from(r))
1307            }
1308
1309            (SimpleNumber::BigInteger(l), SimpleNumber::Real(r)) => {
1310                SimpleNumber::Real(f64::rounding_from(l, RoundingMode::Nearest).0 / *r)
1311            }
1312            (SimpleNumber::Real(l), SimpleNumber::BigInteger(r)) => {
1313                SimpleNumber::Real(*l / f64::rounding_from(r, RoundingMode::Nearest).0)
1314            }
1315
1316            (SimpleNumber::Rational(l), SimpleNumber::Real(r)) => {
1317                SimpleNumber::Real(f64::rounding_from(l, RoundingMode::Nearest).0 / *r)
1318            }
1319            (SimpleNumber::Real(l), SimpleNumber::Rational(r)) => {
1320                SimpleNumber::Real(*l / f64::rounding_from(r, RoundingMode::Nearest).0)
1321            }
1322
1323            (SimpleNumber::FixedInteger(l), SimpleNumber::Real(r)) => {
1324                SimpleNumber::Real(*l as f64 / r)
1325            }
1326            (SimpleNumber::Real(l), SimpleNumber::FixedInteger(r)) => {
1327                SimpleNumber::Real(l / *r as f64)
1328            }
1329        }
1330    }
1331}
1332
1333impl Div for SimpleNumber {
1334    type Output = SimpleNumber;
1335
1336    fn div(self, rhs: SimpleNumber) -> SimpleNumber {
1337        &self / &rhs
1338    }
1339}
1340
1341impl Rem for &'_ SimpleNumber {
1342    type Output = SimpleNumber;
1343
1344    fn rem(self, rhs: &SimpleNumber) -> SimpleNumber {
1345        match (self, rhs) {
1346            (SimpleNumber::FixedInteger(l), SimpleNumber::FixedInteger(r)) => l
1347                .checked_rem(*r)
1348                .map(SimpleNumber::FixedInteger)
1349                .unwrap_or_else(|| {
1350                    SimpleNumber::BigInteger(Integer::from(*l) % (Integer::from(*r)))
1351                }),
1352            (SimpleNumber::BigInteger(l), SimpleNumber::BigInteger(r)) => {
1353                SimpleNumber::BigInteger(l % r)
1354            }
1355            (SimpleNumber::Rational(l), SimpleNumber::Rational(r)) => {
1356                SimpleNumber::Rational(mod_rationals(l, r))
1357            }
1358            (SimpleNumber::Real(l), SimpleNumber::Real(r)) => SimpleNumber::Real(l % r),
1359            (SimpleNumber::BigInteger(l), SimpleNumber::FixedInteger(r)) => {
1360                i64::convertible_from(l)
1361                    .then(|| i64::wrapping_from(l).checked_rem(*r))
1362                    .flatten()
1363                    .map(SimpleNumber::FixedInteger)
1364                    .unwrap_or_else(|| SimpleNumber::BigInteger(l % Integer::from(*r)))
1365            }
1366            (SimpleNumber::FixedInteger(l), SimpleNumber::BigInteger(r)) => {
1367                i64::convertible_from(r)
1368                    .then(|| l.checked_rem(i64::wrapping_from(r)))
1369                    .flatten()
1370                    .map(SimpleNumber::FixedInteger)
1371                    .unwrap_or_else(|| SimpleNumber::BigInteger(Integer::from(*l) % r))
1372            }
1373            (SimpleNumber::Rational(l), SimpleNumber::FixedInteger(r)) => {
1374                SimpleNumber::Rational(mod_rationals(l, &Rational::from(*r)))
1375            }
1376            (SimpleNumber::FixedInteger(l), SimpleNumber::Rational(r)) => {
1377                SimpleNumber::Rational(mod_rationals(&Rational::from(*l), r))
1378            }
1379
1380            (SimpleNumber::Rational(l), SimpleNumber::BigInteger(r)) => {
1381                SimpleNumber::Rational(mod_rationals(l, &Rational::from(r)))
1382            }
1383            (SimpleNumber::BigInteger(l), SimpleNumber::Rational(r)) => {
1384                SimpleNumber::Rational(mod_rationals(&Rational::from(l), r))
1385            }
1386
1387            (SimpleNumber::BigInteger(l), SimpleNumber::Real(r)) => {
1388                SimpleNumber::Real(f64::rounding_from(l, RoundingMode::Nearest).0 % *r)
1389            }
1390            (SimpleNumber::Real(l), SimpleNumber::BigInteger(r)) => {
1391                SimpleNumber::Real(l % f64::rounding_from(r, RoundingMode::Nearest).0)
1392            }
1393
1394            (SimpleNumber::Rational(l), SimpleNumber::Real(r)) => {
1395                SimpleNumber::Real(f64::rounding_from(l, RoundingMode::Nearest).0 % r)
1396            }
1397            (SimpleNumber::Real(l), SimpleNumber::Rational(r)) => {
1398                SimpleNumber::Real(l % f64::rounding_from(r, RoundingMode::Nearest).0)
1399            }
1400
1401            (SimpleNumber::FixedInteger(l), SimpleNumber::Real(r)) => {
1402                SimpleNumber::Real((*l as f64) % r)
1403            }
1404
1405            (SimpleNumber::Real(l), SimpleNumber::FixedInteger(r)) => {
1406                SimpleNumber::Real(l % *r as f64)
1407            }
1408        }
1409    }
1410}
1411
1412fn mod_rationals(lhs: &Rational, rhs: &Rational) -> Rational {
1413    (lhs - rhs) * Rational::from(Integer::rounding_from(lhs / rhs, RoundingMode::Floor).0)
1414}
1415
1416impl Rem for SimpleNumber {
1417    type Output = SimpleNumber;
1418
1419    fn rem(self, rhs: SimpleNumber) -> SimpleNumber {
1420        (&self) % &rhs
1421    }
1422}
1423
1424/// Scheme complex numeric type.
1425#[derive(Clone)]
1426pub struct ComplexNumber {
1427    re: SimpleNumber,
1428    im: SimpleNumber,
1429}
1430
1431impl ComplexNumber {
1432    pub fn new(re: SimpleNumber, im: SimpleNumber) -> Self {
1433        Self { re, im }
1434    }
1435
1436    pub fn is_zero(&self) -> bool {
1437        self.re.is_zero() && self.im.is_zero()
1438    }
1439
1440    pub fn one() -> Self {
1441        Self {
1442            re: SimpleNumber::one(),
1443            im: SimpleNumber::zero(),
1444        }
1445    }
1446
1447    pub fn i() -> Self {
1448        Self {
1449            re: SimpleNumber::zero(),
1450            im: SimpleNumber::one(),
1451        }
1452    }
1453
1454    pub fn inexact(&self) -> Self {
1455        Self {
1456            re: self.re.inexact(),
1457            im: self.im.inexact(),
1458        }
1459    }
1460
1461    pub fn exact(&self) -> Self {
1462        Self {
1463            re: self.re.exact(),
1464            im: self.im.exact(),
1465        }
1466    }
1467
1468    pub fn to_string(&self, radix: u32, precision: Option<usize>) -> Option<String> {
1469        let mut output = self.re.to_string(radix, precision)?;
1470        if self.im.is_exact() && self.im.is_zero() {
1471            return Some(output);
1472        }
1473        if self.im.is_positive() && !self.im.is_nan() && !self.im.is_infinite() {
1474            output.push('+');
1475        }
1476        output.push_str(&self.im.to_string(radix, precision)?);
1477        output.push('i');
1478        Some(output)
1479    }
1480
1481    pub fn from_polar(r: SimpleNumber, theta: SimpleNumber) -> Self {
1482        Self::new(&r * &theta.cos(), &r * &theta.sin())
1483    }
1484
1485    pub fn to_polar(&self) -> (SimpleNumber, SimpleNumber) {
1486        (self.magnitude(), self.arg())
1487    }
1488
1489    pub fn magnitude(&self) -> SimpleNumber {
1490        self.magnitude2().sqrt()
1491    }
1492
1493    pub fn magnitude2(&self) -> SimpleNumber {
1494        self.re.powi(2) + self.im.powi(2)
1495    }
1496
1497    pub fn sqrt(&self) -> Self {
1498        if self.im.is_zero() {
1499            if self.re.is_positive() {
1500                Self::new(self.re.sqrt(), self.im.clone())
1501            } else if self.im.is_positive() {
1502                Self::new(SimpleNumber::zero(), (-&self.re).sqrt())
1503            } else {
1504                Self::new(SimpleNumber::zero(), -(-&self.re).sqrt())
1505            }
1506        } else if self.re.is_zero() {
1507            let x = (self.im.abs() / SimpleNumber::from(2)).sqrt();
1508            if self.im.is_positive() {
1509                Self::new(x.clone(), x)
1510            } else {
1511                Self::new(x.clone(), -x)
1512            }
1513        } else {
1514            let (r, theta) = self.to_polar();
1515            Self::from_polar(r.sqrt(), theta / SimpleNumber::from(2))
1516        }
1517    }
1518
1519    pub fn arg(&self) -> SimpleNumber {
1520        self.im.atan2(&self.re)
1521    }
1522
1523    pub fn exp(&self) -> Self {
1524        Self::from_polar(self.re.exp(), self.im.clone())
1525    }
1526
1527    pub fn ln(&self) -> Self {
1528        let (r, theta) = self.to_polar();
1529        Self::new(r.ln(), theta)
1530    }
1531
1532    pub fn powc(&self, exp: &Self) -> Self {
1533        if exp.is_zero() {
1534            return Self::one();
1535        }
1536        (exp * &self.ln()).exp()
1537    }
1538
1539    pub fn sin(&self) -> Self {
1540        Self::new(
1541            self.re.sin() * self.im.cosh(),
1542            self.re.cos() * self.im.sinh(),
1543        )
1544    }
1545
1546    pub fn cos(&self) -> Self {
1547        Self::new(
1548            self.re.cos() * self.im.cosh(),
1549            -self.re.sin() * self.im.sinh(),
1550        )
1551    }
1552
1553    pub fn tan(&self) -> Self {
1554        let scale = (&self.re + &self.re).cos() + (&self.im + &self.im).cosh();
1555        let re = &(&self.re + &self.re).sin() / &scale;
1556        let im = &(&self.im + &self.im).sinh() / &scale;
1557        Self::new(re, im)
1558    }
1559
1560    pub fn asin(&self) -> Self {
1561        -Self::i() * ((Self::one() - self * self).sqrt() + &Self::i() * self).ln()
1562    }
1563
1564    pub fn acos(&self) -> Self {
1565        -Self::i() * (&(Self::i() * (Self::one() - self * self).sqrt()) + self).ln()
1566    }
1567
1568    pub fn atan(&self) -> Self {
1569        if self.re.is_zero() && self.im.is_one() {
1570            Self::new(SimpleNumber::zero(), SimpleNumber::infinity())
1571        } else if self.re.is_zero() && self.im.is_neg_one() {
1572            Self::new(SimpleNumber::zero(), SimpleNumber::neg_infinity())
1573        } else {
1574            ((&(Self::one() + Self::i()) * self).ln() - (Self::one() - &Self::i() * self).ln())
1575                / ((Self::one() + Self::one()) * Self::i())
1576        }
1577    }
1578}
1579
1580// Any Number can be converted into a ComplexNumber
1581
1582impl From<&Number> for Option<ComplexNumber> {
1583    fn from(value: &Number) -> Self {
1584        match value.0.as_ref() {
1585            NumberInner::Simple(simple) => {
1586                Some(ComplexNumber::new(simple.clone(), SimpleNumber::zero()))
1587            }
1588            NumberInner::Complex(complex) => Some(complex.clone()),
1589        }
1590    }
1591}
1592
1593impl From<Number> for Option<ComplexNumber> {
1594    fn from(value: Number) -> Self {
1595        (&value).into()
1596    }
1597}
1598
1599impl TryFrom<&Number> for ComplexNumber {
1600    type Error = Exception;
1601
1602    fn try_from(value: &Number) -> Result<Self, Self::Error> {
1603        match value.0.as_ref() {
1604            NumberInner::Simple(simple) => {
1605                Ok(ComplexNumber::new(simple.clone(), SimpleNumber::zero()))
1606            }
1607            NumberInner::Complex(complex) => Ok(complex.clone()),
1608        }
1609    }
1610}
1611
1612impl TryFrom<Number> for ComplexNumber {
1613    type Error = Exception;
1614
1615    fn try_from(value: Number) -> Result<Self, Self::Error> {
1616        (&value).try_into()
1617    }
1618}
1619
1620impl From<SimpleNumber> for ComplexNumber {
1621    fn from(value: SimpleNumber) -> Self {
1622        Self {
1623            re: value,
1624            im: SimpleNumber::FixedInteger(0),
1625        }
1626    }
1627}
1628
1629impl PartialEq for ComplexNumber {
1630    fn eq(&self, rhs: &ComplexNumber) -> bool {
1631        self.re == rhs.re && self.im == rhs.im
1632    }
1633}
1634
1635impl Neg for ComplexNumber {
1636    type Output = ComplexNumber;
1637
1638    fn neg(self) -> ComplexNumber {
1639        Self {
1640            re: -self.re,
1641            im: -self.im,
1642        }
1643    }
1644}
1645
1646impl Neg for &ComplexNumber {
1647    type Output = ComplexNumber;
1648
1649    fn neg(self) -> ComplexNumber {
1650        ComplexNumber {
1651            re: -(&self.re),
1652            im: -(&self.im),
1653        }
1654    }
1655}
1656
1657impl Add<&ComplexNumber> for &ComplexNumber {
1658    type Output = ComplexNumber;
1659
1660    fn add(self, rhs: &ComplexNumber) -> ComplexNumber {
1661        ComplexNumber {
1662            re: (&self.re).add(&rhs.re),
1663            im: (&self.im).add(&rhs.im),
1664        }
1665    }
1666}
1667
1668impl Add<ComplexNumber> for ComplexNumber {
1669    type Output = ComplexNumber;
1670
1671    fn add(self, rhs: ComplexNumber) -> ComplexNumber {
1672        ComplexNumber {
1673            re: self.re.add(rhs.re),
1674            im: self.im.add(rhs.im),
1675        }
1676    }
1677}
1678
1679impl Sub<&ComplexNumber> for &ComplexNumber {
1680    type Output = ComplexNumber;
1681
1682    fn sub(self, rhs: &ComplexNumber) -> ComplexNumber {
1683        ComplexNumber {
1684            re: (&self.re).sub(&rhs.re),
1685            im: (&self.im).sub(&rhs.im),
1686        }
1687    }
1688}
1689
1690impl Sub<ComplexNumber> for ComplexNumber {
1691    type Output = ComplexNumber;
1692
1693    fn sub(self, rhs: ComplexNumber) -> ComplexNumber {
1694        ComplexNumber {
1695            re: self.re.sub(rhs.re),
1696            im: self.im.sub(rhs.im),
1697        }
1698    }
1699}
1700
1701impl Mul<&ComplexNumber> for &ComplexNumber {
1702    type Output = ComplexNumber;
1703
1704    fn mul(self, rhs: &ComplexNumber) -> ComplexNumber {
1705        let re = &self.re * &rhs.re - &self.im * &rhs.im;
1706        let im = &self.re * &rhs.im + &self.im * &rhs.re;
1707        ComplexNumber::new(re, im)
1708    }
1709}
1710
1711impl Mul<ComplexNumber> for ComplexNumber {
1712    type Output = ComplexNumber;
1713
1714    fn mul(self, rhs: ComplexNumber) -> ComplexNumber {
1715        (&self).mul(&rhs)
1716    }
1717}
1718
1719impl Div for &ComplexNumber {
1720    type Output = ComplexNumber;
1721
1722    fn div(self, rhs: &ComplexNumber) -> ComplexNumber {
1723        let norm_sqr = rhs.re.powi(2) + rhs.im.powi(2);
1724        let re = self.re.clone() * rhs.re.clone() + self.im.clone() * rhs.im.clone();
1725        let im = self.im.clone() * rhs.re.clone() - self.re.clone() * rhs.im.clone();
1726        ComplexNumber {
1727            re: re / norm_sqr.clone(),
1728            im: im / norm_sqr,
1729        }
1730    }
1731}
1732
1733impl Div for ComplexNumber {
1734    type Output = ComplexNumber;
1735
1736    fn div(self, rhs: ComplexNumber) -> ComplexNumber {
1737        &self / &rhs
1738    }
1739}
1740
1741impl fmt::Display for ComplexNumber {
1742    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1743        write!(f, "{}", self.re)?;
1744        if self.im.is_positive() && !self.im.is_nan() && !self.im.is_infinite() {
1745            write!(f, "+")?;
1746        }
1747        write!(f, "{}i", self.im)
1748    }
1749}
1750
1751impl fmt::Debug for ComplexNumber {
1752    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1753        write!(f, "{:?}", self.re)?;
1754        if self.im.is_positive() && !self.im.is_nan() && !self.im.is_infinite() {
1755            write!(f, "+")?;
1756        }
1757        write!(f, "{:?}i", self.im)
1758    }
1759}
1760
1761impl fmt::Display for Number {
1762    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1763        match self.0.as_ref() {
1764            NumberInner::Simple(simple) => write!(f, "{simple}"),
1765            NumberInner::Complex(complex) => write!(f, "{complex}"),
1766        }
1767    }
1768}
1769
1770impl fmt::Debug for Number {
1771    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1772        match self.0.as_ref() {
1773            NumberInner::Simple(simple) => write!(f, "{simple:?}"),
1774            NumberInner::Complex(complex) => write!(f, "{complex:?}"),
1775        }
1776    }
1777}
1778
1779impl Hash for Number {
1780    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
1781        std::mem::discriminant(self.0.as_ref()).hash(state);
1782        match self.0.as_ref() {
1783            NumberInner::Simple(simple) => simple.hash(state),
1784            NumberInner::Complex(complex) => {
1785                complex.re.hash(state);
1786                complex.im.hash(state);
1787            }
1788        }
1789    }
1790}
1791
1792impl PartialEq for Number {
1793    fn eq(&self, rhs: &Self) -> bool {
1794        match (self.0.as_ref(), rhs.0.as_ref()) {
1795            (NumberInner::Simple(lhs), NumberInner::Simple(rhs)) => lhs.eq(rhs),
1796            (NumberInner::Complex(lhs), NumberInner::Simple(rhs)) if lhs.im.is_zero() => {
1797                lhs.re.eq(rhs)
1798            }
1799            (NumberInner::Simple(lhs), NumberInner::Complex(rhs)) if rhs.im.is_zero() => {
1800                lhs.eq(&rhs.re)
1801            }
1802            (NumberInner::Complex(lhs), NumberInner::Complex(rhs)) => lhs == rhs,
1803            _ => false,
1804        }
1805    }
1806}
1807
1808impl PartialOrd for Number {
1809    fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> {
1810        match (self.0.as_ref(), rhs.0.as_ref()) {
1811            (NumberInner::Simple(lhs), NumberInner::Simple(rhs)) => lhs.partial_cmp(rhs),
1812            (NumberInner::Complex(lhs), NumberInner::Simple(rhs)) if lhs.im.is_zero() => {
1813                lhs.re.partial_cmp(rhs)
1814            }
1815            (NumberInner::Simple(lhs), NumberInner::Complex(rhs)) if rhs.im.is_zero() => {
1816                lhs.partial_cmp(&rhs.re)
1817            }
1818            (NumberInner::Complex(lhs), NumberInner::Complex(rhs))
1819                if lhs.im.is_zero() && rhs.im.is_zero() =>
1820            {
1821                lhs.re.partial_cmp(&rhs.re)
1822            }
1823            _ => None,
1824        }
1825    }
1826}
1827
1828impl Neg for Number {
1829    type Output = Number;
1830
1831    fn neg(self) -> Self {
1832        match self.0.as_ref() {
1833            NumberInner::Simple(this) => Number::from(-this),
1834            NumberInner::Complex(this) => Number::from(-this),
1835        }
1836    }
1837}
1838
1839impl Neg for &'_ Number {
1840    type Output = Number;
1841
1842    fn neg(self) -> Number {
1843        match self.0.as_ref() {
1844            NumberInner::Simple(this) => Number::from(-this),
1845            NumberInner::Complex(this) => Number::from(-this),
1846        }
1847    }
1848}
1849
1850macro_rules! impl_op_for_number {
1851    ($trait:ident, $op:ident) => {
1852        impl $trait for &Number {
1853            type Output = Number;
1854
1855            fn $op(self, rhs: &Number) -> Self::Output {
1856                match (self.0.as_ref(), rhs.0.as_ref()) {
1857                    (NumberInner::Simple(lhs), NumberInner::Simple(rhs)) => {
1858                        Number::from(lhs.$op(rhs))
1859                    }
1860                    (NumberInner::Simple(lhs), NumberInner::Complex(rhs)) => {
1861                        Number::from((&ComplexNumber::from(lhs.clone())).$op(rhs))
1862                    }
1863                    (NumberInner::Complex(lhs), NumberInner::Simple(rhs)) => {
1864                        Number::from(lhs.$op(&ComplexNumber::from(rhs.clone())))
1865                    }
1866                    (NumberInner::Complex(lhs), NumberInner::Complex(rhs)) => {
1867                        Number::from(lhs.$op(rhs))
1868                    }
1869                }
1870            }
1871        }
1872
1873        impl $trait for Number {
1874            type Output = Number;
1875
1876            fn $op(self, rhs: Number) -> Self::Output {
1877                (&self).$op(&rhs)
1878            }
1879        }
1880    };
1881}
1882
1883impl_op_for_number!(Add, add);
1884impl_op_for_number!(Sub, sub);
1885impl_op_for_number!(Mul, mul);
1886impl_op_for_number!(Div, div);
1887
1888////////////////////////////////////////////////////////////////////////////////
1889// Numerical built-ins:
1890
1891#[bridge(name = "number?", lib = "(rnrs base builtins (6))")]
1892pub fn is_number(arg: &Value) -> Result<Vec<Value>, Exception> {
1893    Ok(vec![Value::from(arg.type_of() == ValueType::Number)])
1894}
1895
1896#[bridge(name = "complex?", lib = "(rnrs base builtins (6))")]
1897pub fn is_complex(arg: &Value) -> Result<Vec<Value>, Exception> {
1898    Ok(vec![Value::from(
1899        arg.cast_to_scheme_type::<Number>()
1900            .as_ref()
1901            .is_some_and(Number::is_complex),
1902    )])
1903}
1904
1905#[bridge(name = "real?", lib = "(rnrs base builtins (6))")]
1906pub fn is_real(arg: &Value) -> Result<Vec<Value>, Exception> {
1907    Ok(vec![Value::from(
1908        arg.cast_to_scheme_type::<Number>()
1909            .as_ref()
1910            .is_some_and(Number::is_real),
1911    )])
1912}
1913
1914#[bridge(name = "rational?", lib = "(rnrs base builtins (6))")]
1915pub fn is_rational(arg: &Value) -> Result<Vec<Value>, Exception> {
1916    Ok(vec![Value::from(
1917        arg.cast_to_scheme_type::<Number>()
1918            .as_ref()
1919            .is_some_and(Number::is_rational),
1920    )])
1921}
1922
1923#[bridge(name = "integer?", lib = "(rnrs base builtins (6))")]
1924pub fn is_integer(arg: &Value) -> Result<Vec<Value>, Exception> {
1925    Ok(vec![Value::from(
1926        arg.cast_to_scheme_type::<Number>()
1927            .as_ref()
1928            .is_some_and(Number::is_integer),
1929    )])
1930}
1931
1932#[bridge(name = "real-valued?", lib = "(rnrs base builtins (6))")]
1933pub fn real_valued_pred(arg: &Value) -> Result<Vec<Value>, Exception> {
1934    Ok(vec![Value::from(
1935        arg.cast_to_scheme_type::<Number>()
1936            .as_ref()
1937            .is_some_and(Number::is_real_valued),
1938    )])
1939}
1940
1941#[bridge(name = "rational-valued?", lib = "(rnrs base builtins (6))")]
1942pub fn rational_valued_pred(arg: &Value) -> Result<Vec<Value>, Exception> {
1943    Ok(vec![Value::from(
1944        arg.cast_to_scheme_type::<Number>()
1945            .as_ref()
1946            .is_some_and(Number::is_rational_valued),
1947    )])
1948}
1949
1950#[bridge(name = "integer-valued?", lib = "(rnrs base builtins (6))")]
1951pub fn integer_valued_pred(arg: &Value) -> Result<Vec<Value>, Exception> {
1952    Ok(vec![Value::from(
1953        arg.cast_to_scheme_type::<Number>()
1954            .as_ref()
1955            .is_some_and(Number::is_integer_valued),
1956    )])
1957}
1958
1959#[bridge(name = "exact?", lib = "(rnrs base builtins (6))")]
1960pub fn exact_pred(z: Number) -> Result<Vec<Value>, Exception> {
1961    Ok(vec![Value::from(z.is_exact())])
1962}
1963
1964#[bridge(name = "inexact?", lib = "(rnrs base builtins (6))")]
1965pub fn inexact_pred(z: Number) -> Result<Vec<Value>, Exception> {
1966    Ok(vec![Value::from(z.is_inexact())])
1967}
1968
1969#[bridge(name = "inexact", lib = "(rnrs base builtins (6))")]
1970pub fn inexact(z: Number) -> Result<Vec<Value>, Exception> {
1971    Ok(vec![Value::from(z.inexact())])
1972}
1973
1974#[bridge(name = "exact", lib = "(rnrs base builtins (6))")]
1975pub fn exact(z: Number) -> Result<Vec<Value>, Exception> {
1976    Ok(vec![Value::from(z.exact())])
1977}
1978
1979#[bridge(name = "=", lib = "(rnrs base builtins (6))")]
1980pub fn equal(args: &[Value]) -> Result<Vec<Value>, Exception> {
1981    Ok(vec![Value::from(equal_prim(args)?)])
1982}
1983
1984pub(crate) fn equal_prim(vals: &[Value]) -> Result<bool, Exception> {
1985    if let Some((first, rest)) = vals.split_first() {
1986        let first: Number = first.try_to_scheme_type()?;
1987        for next in rest {
1988            let next: Number = next.try_to_scheme_type()?;
1989            if !(first == next) {
1990                return Ok(false);
1991            }
1992        }
1993    }
1994    Ok(true)
1995}
1996
1997#[bridge(name = "<", lib = "(rnrs base builtins (6))")]
1998pub fn lesser(args: &[Value]) -> Result<Vec<Value>, Exception> {
1999    Ok(vec![Value::from(lesser_prim(args)?)])
2000}
2001
2002pub(crate) fn lesser_prim(vals: &[Value]) -> Result<bool, Exception> {
2003    if let Some((head, rest)) = vals.split_first() {
2004        let mut prev = head.clone();
2005        for next in rest {
2006            let prev_num: Number = prev.try_to_scheme_type()?;
2007            let next_num: Number = next.try_to_scheme_type()?;
2008            if !prev_num.is_real() {
2009                return Err(Exception::type_error("real", "complex"));
2010            }
2011            if !next_num.is_real() {
2012                return Err(Exception::type_error("real", "complex"));
2013            }
2014            if !matches!(prev_num.partial_cmp(&next_num), Some(Ordering::Less)) {
2015                return Ok(false);
2016            }
2017            prev = next.clone();
2018        }
2019    }
2020    Ok(true)
2021}
2022
2023#[bridge(name = ">", lib = "(rnrs base builtins (6))")]
2024pub fn greater(args: &[Value]) -> Result<Vec<Value>, Exception> {
2025    Ok(vec![Value::from(greater_prim(args)?)])
2026}
2027
2028pub(crate) fn greater_prim(vals: &[Value]) -> Result<bool, Exception> {
2029    if let Some((head, rest)) = vals.split_first() {
2030        let mut prev = head.clone();
2031        for next in rest {
2032            let prev_num: Number = prev.try_to_scheme_type()?;
2033            let next_num: Number = next.try_to_scheme_type()?;
2034            // This is somewhat less efficient for small numbers but avoids
2035            // cloning big ones
2036            if !prev_num.is_real() {
2037                return Err(Exception::type_error("real", "complex"));
2038            }
2039            if !next_num.is_real() {
2040                return Err(Exception::type_error("real", "complex"));
2041            }
2042            if !matches!(prev_num.partial_cmp(&next_num), Some(Ordering::Greater)) {
2043                return Ok(false);
2044            }
2045            prev = next.clone();
2046        }
2047    }
2048    Ok(true)
2049}
2050
2051#[bridge(name = "<=", lib = "(rnrs base builtins (6))")]
2052pub fn lesser_equal(args: &[Value]) -> Result<Vec<Value>, Exception> {
2053    Ok(vec![Value::from(lesser_equal_prim(args)?)])
2054}
2055
2056pub(crate) fn lesser_equal_prim(vals: &[Value]) -> Result<bool, Exception> {
2057    if let Some((head, rest)) = vals.split_first() {
2058        let mut prev = head.clone();
2059        for next in rest {
2060            let prev_num: Number = prev.try_to_scheme_type()?;
2061            let next_num: Number = next.try_to_scheme_type()?;
2062            if !prev_num.is_real() {
2063                return Err(Exception::type_error("real", "complex"));
2064            }
2065            if !next_num.is_real() {
2066                return Err(Exception::type_error("real", "complex"));
2067            }
2068            if !matches!(
2069                prev_num.partial_cmp(&next_num),
2070                Some(Ordering::Equal | Ordering::Less)
2071            ) {
2072                return Ok(false);
2073            }
2074            prev = next.clone();
2075        }
2076    }
2077    Ok(true)
2078}
2079
2080#[bridge(name = ">=", lib = "(rnrs base builtins (6))")]
2081pub fn greater_equal(args: &[Value]) -> Result<Vec<Value>, Exception> {
2082    Ok(vec![Value::from(greater_equal_prim(args)?)])
2083}
2084
2085pub(crate) fn greater_equal_prim(vals: &[Value]) -> Result<bool, Exception> {
2086    if let Some((head, rest)) = vals.split_first() {
2087        let mut prev = head.clone();
2088        for next in rest {
2089            let prev_num: Number = prev.try_to_scheme_type()?;
2090            let next_num: Number = next.try_to_scheme_type()?;
2091            if !prev_num.is_real() {
2092                return Err(Exception::type_error("real", "complex"));
2093            }
2094            if !next_num.is_real() {
2095                return Err(Exception::type_error("real", "complex"));
2096            }
2097            if !matches!(
2098                prev_num.partial_cmp(&next_num),
2099                Some(Ordering::Equal | Ordering::Greater)
2100            ) {
2101                return Ok(false);
2102            }
2103            prev = next.clone();
2104        }
2105    }
2106    Ok(true)
2107}
2108
2109#[bridge(name = "zero?", lib = "(rnrs base builtins (6))")]
2110pub fn zero(arg: &Value) -> Result<Vec<Value>, Exception> {
2111    let num: Number = arg.try_to_scheme_type()?;
2112    Ok(vec![Value::from(num.is_zero())])
2113}
2114
2115#[bridge(name = "odd?", lib = "(rnrs base builtins (6))")]
2116pub fn odd(arg: &Value) -> Result<Vec<Value>, Exception> {
2117    let int: Integer = arg.try_to_scheme_type()?;
2118    Ok(vec![Value::from(int.odd())])
2119}
2120
2121#[bridge(name = "even?", lib = "(rnrs base builtins (6))")]
2122pub fn even(arg: &Value) -> Result<Vec<Value>, Exception> {
2123    let int: Integer = arg.try_to_scheme_type()?;
2124    Ok(vec![Value::from(int.even())])
2125}
2126
2127#[bridge(name = "finite?", lib = "(rnrs base builtins (6))")]
2128pub fn is_finite(arg: &Value) -> Result<Vec<Value>, Exception> {
2129    Ok(vec![Value::from(
2130        !arg.try_to_scheme_type::<SimpleNumber>()?.is_infinite(),
2131    )])
2132}
2133
2134#[bridge(name = "infinite?", lib = "(rnrs base builtins (6))")]
2135pub fn is_infinite(arg: &Value) -> Result<Vec<Value>, Exception> {
2136    Ok(vec![Value::from(
2137        arg.try_to_scheme_type::<SimpleNumber>()?.is_infinite(),
2138    )])
2139}
2140
2141#[bridge(name = "nan?", lib = "(rnrs base builtins (6))")]
2142pub fn is_nan(arg: &Value) -> Result<Vec<Value>, Exception> {
2143    Ok(vec![Value::from(
2144        arg.try_to_scheme_type::<SimpleNumber>()?.is_nan(),
2145    )])
2146}
2147
2148#[bridge(name = "+", lib = "(rnrs base builtins (6))")]
2149pub fn add(args: &[Value]) -> Result<Vec<Value>, Exception> {
2150    Ok(vec![Value::from(add_prim(args)?)])
2151}
2152
2153pub(crate) fn add_prim(vals: &[Value]) -> Result<Number, Exception> {
2154    let mut result = Number::from(0i64);
2155    for val in vals {
2156        let num: Number = val.try_to_scheme_type()?;
2157        result = result + num;
2158    }
2159    Ok(result)
2160}
2161
2162#[bridge(name = "*", lib = "(rnrs base builtins (6))")]
2163pub fn mul(args: &[Value]) -> Result<Vec<Value>, Exception> {
2164    Ok(vec![Value::from(mul_prim(args)?)])
2165}
2166
2167pub(crate) fn mul_prim(vals: &[Value]) -> Result<Number, Exception> {
2168    let mut result = Number::from(1i64);
2169    for val in vals {
2170        let num: Number = val.try_to_scheme_type()?;
2171        result = result * num;
2172    }
2173    Ok(result)
2174}
2175
2176#[bridge(name = "-", lib = "(rnrs base builtins (6))")]
2177pub fn sub(arg1: &Value, args: &[Value]) -> Result<Vec<Value>, Exception> {
2178    Ok(vec![Value::from(sub_prim(arg1, args)?)])
2179}
2180
2181pub(crate) fn sub_prim(val1: &Value, vals: &[Value]) -> Result<Number, Exception> {
2182    let val1: Number = val1.try_to_scheme_type()?;
2183    let mut val1 = val1.clone();
2184    if vals.is_empty() {
2185        Ok(-val1)
2186    } else {
2187        for val in vals {
2188            let num: Number = val.try_to_scheme_type()?;
2189            val1 = val1 - num;
2190        }
2191        Ok(val1)
2192    }
2193}
2194
2195#[bridge(name = "/", lib = "(rnrs base builtins (6))")]
2196pub fn div(arg1: &Value, args: &[Value]) -> Result<Vec<Value>, Exception> {
2197    Ok(vec![Value::from(div_prim(arg1, args)?)])
2198}
2199
2200pub(crate) fn div_prim(val1: &Value, vals: &[Value]) -> Result<Number, Exception> {
2201    let mut is_exact = true;
2202    let val1: Number = val1.try_to_scheme_type()?;
2203    is_exact &= val1.is_exact();
2204    if vals.is_empty() {
2205        if val1.is_zero() && is_exact {
2206            return Err(Exception::error("division by zero"));
2207        } else {
2208            return Ok(Number::from(1) / val1);
2209        }
2210    }
2211    let mut result = val1.clone();
2212    for val in vals {
2213        let num: Number = val.try_to_scheme_type()?;
2214        is_exact &= num.is_exact();
2215        if num.is_zero() && is_exact {
2216            return Err(Exception::error("division by zero"));
2217        }
2218        result = result / num;
2219    }
2220    Ok(result)
2221}
2222
2223#[bridge(name = "div-and-mod", lib = "(rnrs base builtins (6))")]
2224pub fn div_mod(x1: SimpleNumber, x2: SimpleNumber) -> Result<Vec<Value>, Exception> {
2225    if x2.is_zero() {
2226        return Err(Exception::error("division by zero"));
2227    }
2228    let nd = x1.div_euclid(&x2);
2229    let nd_x2 = &x2 * &nd;
2230    let modulo = if nd_x2 < x1 { x1 - nd_x2 } else { nd_x2 - x1 };
2231    Ok(vec![Value::from(nd), Value::from(modulo)])
2232}
2233
2234#[bridge(name = "div", lib = "(rnrs base builtins (6))")]
2235pub fn integer_division(x1: SimpleNumber, x2: SimpleNumber) -> Result<Vec<Value>, Exception> {
2236    if x2.is_zero() {
2237        return Err(Exception::error("division by zero"));
2238    }
2239    let nd = x1.div_euclid(&x2);
2240    Ok(vec![Value::from(nd)])
2241}
2242
2243#[bridge(name = "mod", lib = "(rnrs base builtins (6))")]
2244pub fn modulo(x1: SimpleNumber, x2: SimpleNumber) -> Result<Vec<Value>, Exception> {
2245    if x2.is_zero() {
2246        return Err(Exception::error("modulo by zero"));
2247    }
2248    let nd = x1.div_euclid(&x2);
2249    let nd_x2 = &x2 * &nd;
2250    if nd_x2 < x1 {
2251        Ok(vec![Value::from(x1 - nd_x2)])
2252    } else {
2253        Ok(vec![Value::from(nd_x2 - x1)])
2254    }
2255}
2256
2257#[bridge(name = "numerator", lib = "(rnrs base builtins (6))")]
2258pub fn numerator(obj: &Value) -> Result<Vec<Value>, Exception> {
2259    match obj.try_to_scheme_type::<SimpleNumber>()? {
2260        SimpleNumber::Rational(r) => Ok(vec![Value::from(Integer::from_sign_and_abs(
2261            r >= 0i64,
2262            r.into_numerator(),
2263        ))]),
2264        _ => Ok(vec![obj.clone()]),
2265    }
2266}
2267
2268#[bridge(name = "denominator", lib = "(rnrs base builtins (6))")]
2269pub fn denominator(obj: &Value) -> Result<Vec<Value>, Exception> {
2270    match obj.try_to_scheme_type::<SimpleNumber>()? {
2271        SimpleNumber::Rational(r) => Ok(vec![Value::from(Integer::from(r.into_denominator()))]),
2272        SimpleNumber::Real(r) => Ok(vec![Value::from(
2273            f64::rounding_from(
2274                &Rational::try_from_float_simplest(r)
2275                    .map_err(|_| Exception::error("not a rational"))?
2276                    .into_denominator(),
2277                RoundingMode::Nearest,
2278            )
2279            .0,
2280        )]),
2281        _ => Ok(vec![Value::from(1)]),
2282    }
2283}
2284
2285#[bridge(name = "floor", lib = "(rnrs base builtins (6))")]
2286pub fn floor(obj: &Value) -> Result<Vec<Value>, Exception> {
2287    match obj.try_to_scheme_type::<SimpleNumber>()? {
2288        SimpleNumber::Rational(r) => Ok(vec![Value::from(
2289            Integer::rounding_from(r, RoundingMode::Floor).0,
2290        )]),
2291        SimpleNumber::Real(r) => Ok(vec![Value::from(r.floor())]),
2292        _ => Ok(vec![obj.clone()]),
2293    }
2294}
2295
2296#[bridge(name = "ceiling", lib = "(rnrs base builtins (6))")]
2297pub fn ceiling(obj: &Value) -> Result<Vec<Value>, Exception> {
2298    match obj.try_to_scheme_type::<SimpleNumber>()? {
2299        SimpleNumber::Rational(r) => Ok(vec![Value::from(
2300            Integer::rounding_from(r, RoundingMode::Ceiling).0,
2301        )]),
2302        SimpleNumber::Real(r) => Ok(vec![Value::from(r.ceil())]),
2303        _ => Ok(vec![obj.clone()]),
2304    }
2305}
2306
2307#[bridge(name = "truncate", lib = "(rnrs base builtins (6))")]
2308pub fn truncate(obj: &Value) -> Result<Vec<Value>, Exception> {
2309    match obj.try_to_scheme_type::<SimpleNumber>()? {
2310        SimpleNumber::Rational(r) => Ok(vec![Value::from(
2311            Integer::rounding_from(r, RoundingMode::Down).0,
2312        )]),
2313        SimpleNumber::Real(r) => Ok(vec![Value::from(r.trunc())]),
2314        _ => Ok(vec![obj.clone()]),
2315    }
2316}
2317
2318#[bridge(name = "round", lib = "(rnrs base builtins (6))")]
2319pub fn round(obj: &Value) -> Result<Vec<Value>, Exception> {
2320    match obj.try_to_scheme_type::<SimpleNumber>()? {
2321        SimpleNumber::Rational(r) => Ok(vec![Value::from(
2322            Integer::rounding_from(r, RoundingMode::Nearest).0,
2323        )]),
2324        SimpleNumber::Real(r) => Ok(vec![Value::from(r.round_ties_even())]),
2325        _ => Ok(vec![obj.clone()]),
2326    }
2327}
2328
2329#[bridge(name = "exp", lib = "(rnrs base builtins (6))")]
2330pub fn exp(z: &Value) -> Result<Vec<Value>, Exception> {
2331    Ok(vec![Value::from(z.try_to_scheme_type::<Number>()?.exp())])
2332}
2333
2334#[bridge(name = "log", lib = "(rnrs base builtins (6))")]
2335pub fn log(z: &Value, base: &[Value]) -> Result<Vec<Value>, Exception> {
2336    let base = match base {
2337        [] => None,
2338        [base] => Some(base.try_to_scheme_type::<f64>()?),
2339        _ => return Err(Exception::error("too many arguments")),
2340    };
2341    let num = match z.try_to_scheme_type::<SimpleNumber>()? {
2342        SimpleNumber::FixedInteger(i) => i as f64,
2343        SimpleNumber::BigInteger(i) => f64::rounding_from(&i, RoundingMode::Nearest).0,
2344        SimpleNumber::Rational(r) => f64::rounding_from(&r, RoundingMode::Nearest).0,
2345        SimpleNumber::Real(r) => r,
2346    };
2347    if let Some(base) = base {
2348        Ok(vec![Value::from(num.log(base))])
2349    } else {
2350        Ok(vec![Value::from(num.ln())])
2351    }
2352}
2353
2354#[bridge(name = "sin", lib = "(rnrs base builtins (6))")]
2355pub fn sin(z: Number) -> Result<Vec<Value>, Exception> {
2356    Ok(vec![Value::from(z.sin())])
2357}
2358
2359#[bridge(name = "cos", lib = "(rnrs base builtins (6))")]
2360pub fn cos(z: Number) -> Result<Vec<Value>, Exception> {
2361    Ok(vec![Value::from(z.cos())])
2362}
2363
2364#[bridge(name = "tan", lib = "(rnrs base builtins (6))")]
2365pub fn tan(z: Number) -> Result<Vec<Value>, Exception> {
2366    Ok(vec![Value::from(z.tan())])
2367}
2368
2369#[bridge(name = "asin", lib = "(rnrs base builtins (6))")]
2370pub fn asin(z: Number) -> Result<Vec<Value>, Exception> {
2371    Ok(vec![Value::from(z.asin())])
2372}
2373
2374#[bridge(name = "acos", lib = "(rnrs base builtins (6))")]
2375pub fn acos(z: Number) -> Result<Vec<Value>, Exception> {
2376    Ok(vec![Value::from(z.acos())])
2377}
2378
2379#[bridge(name = "atan", lib = "(rnrs base builtins (6))")]
2380pub fn atan(z: Number) -> Result<Vec<Value>, Exception> {
2381    Ok(vec![Value::from(z.atan())])
2382}
2383
2384#[bridge(name = "sqrt", lib = "(rnrs base builtins (6))")]
2385pub fn sqrt(z: &Value) -> Result<Vec<Value>, Exception> {
2386    Ok(vec![Value::from(z.try_to_scheme_type::<Number>()?.sqrt())])
2387}
2388
2389#[bridge(name = "exact-integer-sqrt", lib = "(rnrs base builtins (6))")]
2390pub fn exact_integer_sqrt(arg: Integer) -> Result<Vec<Value>, Exception> {
2391    let s = (&arg).floor_sqrt();
2392    let r = arg - &s * &s;
2393    Ok(vec![Value::from(s), Value::from(r)])
2394}
2395
2396#[bridge(name = "expt", lib = "(rnrs base builtins (6))")]
2397pub fn expt(z1: &Value, z2: &Value) -> Result<Vec<Value>, Exception> {
2398    let z1 = z1.try_to_scheme_type::<Number>()?;
2399    let z2 = z2.try_to_scheme_type::<Number>()?;
2400    Ok(vec![Value::from(z1.pow(&z2))])
2401}
2402
2403#[bridge(name = "make-rectangular", lib = "(rnrs base builtins (6))")]
2404pub fn make_rectangular(x1: SimpleNumber, x2: SimpleNumber) -> Result<Vec<Value>, Exception> {
2405    Ok(vec![Value::from(ComplexNumber::new(x1, x2))])
2406}
2407
2408#[bridge(name = "make-polar", lib = "(rnrs base builtins (6))")]
2409pub fn make_polar(x1: SimpleNumber, x2: SimpleNumber) -> Result<Vec<Value>, Exception> {
2410    Ok(vec![Value::from(ComplexNumber::from_polar(x1, x2))])
2411}
2412
2413#[bridge(name = "real-part", lib = "(rnrs base builtins (6))")]
2414pub fn real_part(arg: &Value) -> Result<Vec<Value>, Exception> {
2415    let num: Number = arg.try_to_scheme_type()?;
2416    if let Some(complex) = num.as_complex() {
2417        Ok(vec![Value::from(complex.re.clone())])
2418    } else {
2419        Ok(vec![arg.clone()])
2420    }
2421}
2422
2423#[bridge(name = "imag-part", lib = "(rnrs base builtins (6))")]
2424pub fn imag_part(arg: &Value) -> Result<Vec<Value>, Exception> {
2425    let num: Number = arg.try_to_scheme_type()?;
2426    if let Some(complex) = num.as_complex() {
2427        Ok(vec![Value::from(complex.im.clone())])
2428    } else {
2429        Err(Exception::error("expected complex number"))
2430    }
2431}
2432
2433#[bridge(name = "magnitude", lib = "(rnrs base builtins (6))")]
2434pub fn magnitude(arg: &Value) -> Result<Vec<Value>, Exception> {
2435    let num: Number = arg.try_to_scheme_type()?;
2436    if let Some(complex) = num.as_complex() {
2437        Ok(vec![Value::from(complex.magnitude())])
2438    } else {
2439        Ok(vec![arg.clone()])
2440    }
2441}
2442
2443#[bridge(name = "angle", lib = "(rnrs base builtins (6))")]
2444pub fn angle(z: ComplexNumber) -> Result<Vec<Value>, Exception> {
2445    let (_, angle) = z.to_polar();
2446    Ok(vec![Value::from(angle)])
2447}
2448
2449#[bridge(name = "number->string", lib = "(rnrs base builtins (6))")]
2450pub fn number_to_string(z: ComplexNumber, rest_args: &[Value]) -> Result<Vec<Value>, Exception> {
2451    let (radix, precision) = match rest_args {
2452        [] => (10, None),
2453        [radix] => (radix.try_to_scheme_type::<u32>()?, None),
2454        [radix, precision] => (
2455            radix.try_to_scheme_type::<u32>()?,
2456            Some(precision.try_to_scheme_type::<usize>()?),
2457        ),
2458        _ => return Err(Exception::wrong_num_of_var_args(2..3, 1 + rest_args.len())),
2459    };
2460    if !matches!(radix, 2 | 8 | 10 | 16) {
2461        return Err(Exception::error(format!(
2462            "invalid radix ({radix}) must be 2, 8, 10 or 16"
2463        )));
2464    }
2465    let result = z.to_string(radix, precision).ok_or_else(|| {
2466        Exception::implementation_restriction(format!("could not format {z} with radix {radix}"))
2467    })?;
2468    Ok(vec![Value::from(result)])
2469}
2470
2471#[maybe_async]
2472#[bridge(name = "string->number", lib = "(rnrs base builtins (6))")]
2473pub fn string_to_number(s: WideString, rest_args: &[Value]) -> Result<Vec<Value>, Exception> {
2474    let radix = match rest_args {
2475        [] => 10,
2476        [radix] => match radix.try_to_scheme_type::<u32>()? {
2477            radix @ (2 | 8 | 10 | 16) => radix,
2478            radix => {
2479                return Err(Exception::error(format!(
2480                    "invalid radix ({radix}) must be 2, 8, 10 or 16"
2481                )));
2482            }
2483        },
2484        _ => return Err(Exception::wrong_num_of_var_args(1..2, 1 + rest_args.len())),
2485    };
2486    // TODO: This is not ideal
2487    let s = s.to_string();
2488    let bytes = Cursor::new(s.as_bytes().to_vec());
2489    let port = Port::new("", bytes, BufferMode::Block, Some(Transcoder::native()));
2490    let info = &port.0.info;
2491    #[cfg(not(feature = "async"))]
2492    let mut data = port.0.data.lock().unwrap();
2493    #[cfg(feature = "tokio")]
2494    let mut data = port.0.data.lock().await;
2495    let mut lexer = Lexer::new(&mut data, info, Span::default());
2496    let Some(number) = maybe_await!(lexer.number(radix)).ok().flatten() else {
2497        return Ok(vec![Value::from(false)]);
2498    };
2499
2500    if maybe_await!(lexer.take()).ok().flatten().is_some() {
2501        return Ok(vec![Value::from(false)]);
2502    }
2503
2504    let Ok(number) = Number::try_from(number) else {
2505        return Ok(vec![Value::from(false)]);
2506    };
2507
2508    Ok(vec![Value::from(number)])
2509}
2510
2511/// R6RS Fixnums
2512pub struct Fixnum(pub i64);
2513
2514impl From<&Value> for Option<Fixnum> {
2515    fn from(value: &Value) -> Option<Fixnum> {
2516        if let Some(num) = value.cast_to_scheme_type::<Number>()
2517            && let NumberInner::Simple(simple) = &*num.0
2518            && let SimpleNumber::FixedInteger(fixnum) = simple
2519        {
2520            Some(Fixnum(*fixnum))
2521        } else {
2522            None
2523        }
2524    }
2525}
2526
2527impl TryFrom<&Value> for Fixnum {
2528    type Error = Exception;
2529
2530    fn try_from(value: &Value) -> Result<Self, Self::Error> {
2531        if let Some(num) = value.cast_to_scheme_type::<Number>()
2532            && let NumberInner::Simple(simple) = &*num.0
2533            && let SimpleNumber::FixedInteger(fixnum) = simple
2534        {
2535            Ok(Fixnum(*fixnum))
2536        } else {
2537            Err(Exception::error("value is not a fixnum"))
2538        }
2539    }
2540}
2541
2542#[bridge(name = "fixnum?", lib = "(rnrs arithmetic fixnums (6))")]
2543pub fn fixnum_pred(obj: &Value) -> Result<Vec<Value>, Exception> {
2544    Ok(vec![Value::from(
2545        obj.cast_to_scheme_type::<Fixnum>().is_some(),
2546    )])
2547}
2548
2549#[bridge(name = "fixnum-width", lib = "(rnrs arithmetic fixnums (6))")]
2550pub fn fixnum_width() -> Result<Vec<Value>, Exception> {
2551    Ok(vec![Value::from(64)])
2552}
2553
2554#[bridge(name = "least-fixnum", lib = "(rnrs arithmetic fixnums (6))")]
2555pub fn least_fixnum() -> Result<Vec<Value>, Exception> {
2556    Ok(vec![Value::from(i64::MIN)])
2557}
2558
2559#[bridge(name = "greatest-fixnum", lib = "(rnrs arithmetic fixnums (6))")]
2560pub fn greatest_fixnum() -> Result<Vec<Value>, Exception> {
2561    Ok(vec![Value::from(i64::MAX)])
2562}
2563
2564/// R6RS Flonums
2565pub struct Flonum(pub f64);
2566
2567impl From<&Value> for Option<Flonum> {
2568    fn from(value: &Value) -> Option<Flonum> {
2569        if let Some(num) = value.cast_to_scheme_type::<Number>()
2570            && let NumberInner::Simple(simple) = &*num.0
2571            && let SimpleNumber::Real(flonum) = simple
2572        {
2573            Some(Flonum(*flonum))
2574        } else {
2575            None
2576        }
2577    }
2578}
2579
2580impl TryFrom<&Value> for Flonum {
2581    type Error = Exception;
2582
2583    fn try_from(value: &Value) -> Result<Self, Self::Error> {
2584        if let Some(num) = value.cast_to_scheme_type::<Number>()
2585            && let NumberInner::Simple(simple) = &*num.0
2586            && let SimpleNumber::Real(flonum) = simple
2587        {
2588            Ok(Flonum(*flonum))
2589        } else {
2590            Err(Exception::error("value is not a flonum"))
2591        }
2592    }
2593}
2594
2595#[bridge(name = "flonum?", lib = "(rnrs arithmetic flonums (6))")]
2596pub fn flonum_pred(obj: &Value) -> Result<Vec<Value>, Exception> {
2597    Ok(vec![Value::from(
2598        obj.cast_to_scheme_type::<Flonum>().is_some(),
2599    )])
2600}