artichoke_backend/extn/core/math/
trampoline.rs

1//! Glue between mruby FFI and `ENV` Rust implementation.
2
3use std::fmt::Write as _;
4
5use crate::convert::implicitly_convert_to_int;
6use crate::extn::prelude::*;
7use crate::fmt::WriteError;
8
9pub fn acos(interp: &mut Artichoke, value: Value) -> Result<f64, Error> {
10    let value = interp.coerce_to_float(value)?;
11    let result = spinoso_math::acos(value)?;
12    Ok(result)
13}
14
15pub fn acosh(interp: &mut Artichoke, value: Value) -> Result<f64, Error> {
16    let value = interp.coerce_to_float(value)?;
17    let result = spinoso_math::acosh(value)?;
18    Ok(result)
19}
20
21pub fn asin(interp: &mut Artichoke, value: Value) -> Result<f64, Error> {
22    let value = interp.coerce_to_float(value)?;
23    let result = spinoso_math::asin(value)?;
24    Ok(result)
25}
26
27pub fn asinh(interp: &mut Artichoke, value: Value) -> Result<f64, Error> {
28    let value = interp.coerce_to_float(value)?;
29    let result = spinoso_math::asinh(value);
30    Ok(result)
31}
32
33pub fn atan(interp: &mut Artichoke, value: Value) -> Result<f64, Error> {
34    let value = interp.coerce_to_float(value)?;
35    let result = spinoso_math::atan(value);
36    Ok(result)
37}
38
39pub fn atan2(interp: &mut Artichoke, value: Value, other: Value) -> Result<f64, Error> {
40    let value = interp.coerce_to_float(value)?;
41    let other = interp.coerce_to_float(other)?;
42    let result = spinoso_math::atan2(value, other);
43    Ok(result)
44}
45
46pub fn atanh(interp: &mut Artichoke, value: Value) -> Result<f64, Error> {
47    let value = interp.coerce_to_float(value)?;
48    let result = spinoso_math::atanh(value)?;
49    Ok(result)
50}
51
52pub fn cbrt(interp: &mut Artichoke, value: Value) -> Result<f64, Error> {
53    let value = interp.coerce_to_float(value)?;
54    let result = spinoso_math::cbrt(value);
55    Ok(result)
56}
57
58pub fn cos(interp: &mut Artichoke, value: Value) -> Result<f64, Error> {
59    let value = interp.coerce_to_float(value)?;
60    let result = spinoso_math::cos(value);
61    Ok(result)
62}
63
64pub fn cosh(interp: &mut Artichoke, value: Value) -> Result<f64, Error> {
65    let value = interp.coerce_to_float(value)?;
66    let result = spinoso_math::cosh(value);
67    Ok(result)
68}
69
70pub fn erf(interp: &mut Artichoke, value: Value) -> Result<f64, Error> {
71    let value = interp.coerce_to_float(value)?;
72    let result = spinoso_math::erf(value)?;
73    Ok(result)
74}
75
76pub fn erfc(interp: &mut Artichoke, value: Value) -> Result<f64, Error> {
77    let value = interp.coerce_to_float(value)?;
78    let result = spinoso_math::erfc(value)?;
79    Ok(result)
80}
81
82pub fn exp(interp: &mut Artichoke, value: Value) -> Result<f64, Error> {
83    let value = interp.coerce_to_float(value)?;
84    let result = spinoso_math::exp(value);
85    Ok(result)
86}
87
88pub fn frexp(interp: &mut Artichoke, value: Value) -> Result<(f64, i64), Error> {
89    let value = interp.coerce_to_float(value)?;
90    let (fraction, exponent) = spinoso_math::frexp(value)?;
91    Ok((fraction, exponent.into()))
92}
93
94pub fn gamma(interp: &mut Artichoke, value: Value) -> Result<f64, Error> {
95    let value = interp.coerce_to_float(value)?;
96    let result = spinoso_math::gamma(value)?;
97    Ok(result)
98}
99
100pub fn hypot(interp: &mut Artichoke, value: Value, other: Value) -> Result<f64, Error> {
101    let value = interp.coerce_to_float(value)?;
102    let other = interp.coerce_to_float(other)?;
103    let result = spinoso_math::hypot(value, other);
104    Ok(result)
105}
106
107#[expect(
108    clippy::cast_possible_truncation,
109    reason = "XXX: explain reason - https://github.com/artichoke/artichoke/pull/2813"
110)]
111pub fn ldexp(interp: &mut Artichoke, fraction: Value, exponent: Value) -> Result<f64, Error> {
112    let fraction = interp.coerce_to_float(fraction)?;
113    let exponent = implicitly_convert_to_int(interp, exponent).map_err(|_| exponent.try_convert_into::<f64>(interp));
114    let exponent = match exponent {
115        Ok(exp) => exp,
116        Err(Ok(exp)) if exp.is_nan() => {
117            return Err(RangeError::with_message("float NaN out of range of integer").into());
118        }
119        Err(Ok(exp)) => {
120            // This saturating cast will be rejected by the `i32::try_from`
121            // below if `exp` is too large.
122            exp as i64
123        }
124        Err(Err(err)) => return Err(err),
125    };
126    match i32::try_from(exponent) {
127        Ok(exp) => {
128            let result = spinoso_math::ldexp(fraction, exp)?;
129            Ok(result)
130        }
131        Err(_) if exponent < 0 => {
132            let mut message = String::new();
133            write!(&mut message, "integer {exponent} too small to convert to `int'").map_err(WriteError::from)?;
134            Err(RangeError::from(message).into())
135        }
136        Err(_) => {
137            let mut message = String::new();
138            write!(&mut message, "integer {exponent} too big to convert to `int'").map_err(WriteError::from)?;
139            Err(RangeError::from(message).into())
140        }
141    }
142}
143
144pub fn lgamma(interp: &mut Artichoke, value: Value) -> Result<(f64, i64), Error> {
145    let value = interp.coerce_to_float(value)?;
146    let (result, sign) = spinoso_math::lgamma(value)?;
147    Ok((result, sign.into()))
148}
149
150pub fn log(interp: &mut Artichoke, value: Value, base: Option<Value>) -> Result<f64, Error> {
151    let value = interp.coerce_to_float(value)?;
152    let base = if let Some(base) = base {
153        let base = interp.coerce_to_float(base)?;
154        Some(base)
155    } else {
156        None
157    };
158    let result = spinoso_math::log(value, base)?;
159    Ok(result)
160}
161
162pub fn log10(interp: &mut Artichoke, value: Value) -> Result<f64, Error> {
163    let value = interp.coerce_to_float(value)?;
164    let result = spinoso_math::log10(value)?;
165    Ok(result)
166}
167
168pub fn log2(interp: &mut Artichoke, value: Value) -> Result<f64, Error> {
169    let value = interp.coerce_to_float(value)?;
170    let result = spinoso_math::log2(value)?;
171    Ok(result)
172}
173
174pub fn sin(interp: &mut Artichoke, value: Value) -> Result<f64, Error> {
175    let value = interp.coerce_to_float(value)?;
176    let result = value.sin();
177    Ok(result)
178}
179
180pub fn sinh(interp: &mut Artichoke, value: Value) -> Result<f64, Error> {
181    let value = interp.coerce_to_float(value)?;
182    let result = spinoso_math::sinh(value);
183    Ok(result)
184}
185
186pub fn sqrt(interp: &mut Artichoke, value: Value) -> Result<f64, Error> {
187    let value = interp.coerce_to_float(value)?;
188    let result = spinoso_math::sqrt(value)?;
189    Ok(result)
190}
191
192pub fn tan(interp: &mut Artichoke, value: Value) -> Result<f64, Error> {
193    let value = interp.coerce_to_float(value)?;
194    let result = spinoso_math::tan(value);
195    Ok(result)
196}
197
198pub fn tanh(interp: &mut Artichoke, value: Value) -> Result<f64, Error> {
199    let value = interp.coerce_to_float(value)?;
200    let result = spinoso_math::tanh(value);
201    Ok(result)
202}