rune/modules/
f64.rs

1//! Floating point numbers.
2
3use core::cmp::Ordering;
4use core::num::ParseFloatError;
5
6use crate as rune;
7use crate::runtime::{VmErrorKind, VmResult};
8use crate::{ContextError, Module};
9
10/// Floating point numbers.
11///
12/// This provides methods for computing over and parsing 64-bit floating pointer
13/// numbers.
14#[rune::module(::std::f64)]
15pub fn module() -> Result<Module, ContextError> {
16    let mut m = Module::from_meta(self::module_meta)?;
17
18    m.function_meta(parse)?
19        .deprecated("Use std::string::parse::<f64> instead")?;
20    m.function_meta(is_nan)?;
21    m.function_meta(is_infinite)?;
22    m.function_meta(is_finite)?;
23    m.function_meta(is_subnormal)?;
24    m.function_meta(is_normal)?;
25    m.function_meta(max__meta)?;
26    m.function_meta(min__meta)?;
27    #[cfg(feature = "std")]
28    m.function_meta(sqrt)?;
29    #[cfg(feature = "std")]
30    m.function_meta(abs)?;
31    #[cfg(feature = "std")]
32    m.function_meta(powf)?;
33    #[cfg(feature = "std")]
34    m.function_meta(powi)?;
35    #[cfg(feature = "std")]
36    m.function_meta(floor)?;
37    #[cfg(feature = "std")]
38    m.function_meta(ceil)?;
39    #[cfg(feature = "std")]
40    m.function_meta(round)?;
41    m.function_meta(to_integer)?;
42
43    m.function_meta(clone__meta)?;
44    m.implement_trait::<f64>(rune::item!(::std::clone::Clone))?;
45
46    m.function_meta(partial_eq__meta)?;
47    m.implement_trait::<f64>(rune::item!(::std::cmp::PartialEq))?;
48
49    m.function_meta(eq__meta)?;
50    m.implement_trait::<f64>(rune::item!(::std::cmp::Eq))?;
51
52    m.function_meta(partial_cmp__meta)?;
53    m.implement_trait::<f64>(rune::item!(::std::cmp::PartialOrd))?;
54
55    m.function_meta(cmp__meta)?;
56    m.implement_trait::<f64>(rune::item!(::std::cmp::Ord))?;
57
58    m.constant("EPSILON", f64::EPSILON).build()?;
59    m.constant("MIN", f64::MIN).build()?;
60    m.constant("MAX", f64::MAX).build()?;
61    m.constant("MIN_POSITIVE", f64::MIN_POSITIVE).build()?;
62    m.constant("MIN_EXP", f64::MIN_EXP).build()?;
63    m.constant("MAX_EXP", f64::MAX_EXP).build()?;
64    m.constant("MIN_10_EXP", f64::MIN_10_EXP).build()?;
65    m.constant("MAX_10_EXP", f64::MAX_10_EXP).build()?;
66    m.constant("NAN", f64::NAN).build()?;
67    m.constant("INFINITY", f64::INFINITY).build()?;
68    m.constant("NEG_INFINITY", f64::NEG_INFINITY).build()?;
69    Ok(m)
70}
71
72#[rune::function]
73fn parse(s: &str) -> Result<f64, ParseFloatError> {
74    str::parse::<f64>(s)
75}
76
77/// Convert a float to a an integer.
78///
79/// # Examples
80///
81/// ```rune
82/// let n = 7.0_f64.to::<i64>();
83/// assert_eq!(n, 7);
84/// ```
85#[rune::function(instance, path = to::<i64>)]
86fn to_integer(value: f64) -> i64 {
87    value as i64
88}
89
90/// Returns `true` if this value is NaN.
91///
92/// # Examples
93///
94/// ```rune
95/// let nan = f64::NAN;
96/// let f = 7.0_f64;
97///
98/// assert!(nan.is_nan());
99/// assert!(!f.is_nan());
100/// ```
101#[rune::function(instance)]
102fn is_nan(this: f64) -> bool {
103    this.is_nan()
104}
105
106/// Returns `true` if this value is positive infinity or negative infinity, and
107/// `false` otherwise.
108///
109/// # Examples
110///
111/// ```rune
112/// let f = 7.0f64;
113/// let inf = f64::INFINITY;
114/// let neg_inf = f64::NEG_INFINITY;
115/// let nan = f64::NAN;
116///
117/// assert!(!f.is_infinite());
118/// assert!(!nan.is_infinite());
119///
120/// assert!(inf.is_infinite());
121/// assert!(neg_inf.is_infinite());
122/// ```
123#[rune::function(instance)]
124fn is_infinite(this: f64) -> bool {
125    this.is_infinite()
126}
127
128/// Returns `true` if this number is neither infinite nor NaN.
129///
130/// # Examples
131///
132/// ```rune
133/// let f = 7.0f64;
134/// let inf = f64::INFINITY;
135/// let neg_inf = f64::NEG_INFINITY;
136/// let nan = f64::NAN;
137///
138/// assert!(f.is_finite());
139///
140/// assert!(!nan.is_finite());
141/// assert!(!inf.is_finite());
142/// assert!(!neg_inf.is_finite());
143/// ```
144#[rune::function(instance)]
145fn is_finite(this: f64) -> bool {
146    this.is_finite()
147}
148
149/// Returns `true` if the number is [subnormal].
150///
151/// # Examples
152///
153/// ```rune
154/// let min = f64::MIN_POSITIVE; // 2.2250738585072014e-308_f64
155/// let max = f64::MAX;
156/// let lower_than_min = 1.0e-308_f64;
157/// let zero = 0.0_f64;
158///
159/// assert!(!min.is_subnormal());
160/// assert!(!max.is_subnormal());
161///
162/// assert!(!zero.is_subnormal());
163/// assert!(!f64::NAN.is_subnormal());
164/// assert!(!f64::INFINITY.is_subnormal());
165/// // Values between `0` and `min` are Subnormal.
166/// assert!(lower_than_min.is_subnormal());
167/// ```
168///
169/// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number
170#[rune::function(instance)]
171fn is_subnormal(this: f64) -> bool {
172    this.is_subnormal()
173}
174
175/// Returns `true` if the number is neither zero, infinite, [subnormal], or NaN.
176///
177/// # Examples
178///
179/// ```rune
180/// let min = f64::MIN_POSITIVE; // 2.2250738585072014e-308f64
181/// let max = f64::MAX;
182/// let lower_than_min = 1.0e-308_f64;
183/// let zero = 0.0f64;
184///
185/// assert!(min.is_normal());
186/// assert!(max.is_normal());
187///
188/// assert!(!zero.is_normal());
189/// assert!(!f64::NAN.is_normal());
190/// assert!(!f64::INFINITY.is_normal());
191/// // Values between `0` and `min` are Subnormal.
192/// assert!(!lower_than_min.is_normal());
193/// ```
194/// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number
195#[rune::function(instance)]
196fn is_normal(this: f64) -> bool {
197    this.is_normal()
198}
199
200/// Returns the maximum of the two numbers, ignoring NaN.
201///
202/// If one of the arguments is NaN, then the other argument is returned. This
203/// follows the IEEE 754-2008 semantics for maxNum, except for handling of
204/// signaling NaNs; this function handles all NaNs the same way and avoids
205/// maxNum's problems with associativity. This also matches the behavior of
206/// libm’s fmax.
207///
208/// # Examples
209///
210/// ```rune
211/// let x = 1.0_f64;
212/// let y = 2.0_f64;
213///
214/// assert_eq!(x.max(y), y);
215/// ```
216#[rune::function(keep, instance, protocol = MAX)]
217fn max(this: f64, other: f64) -> f64 {
218    this.max(other)
219}
220
221/// Returns the minimum of the two numbers, ignoring NaN.
222///
223/// If one of the arguments is NaN, then the other argument is returned. This
224/// follows the IEEE 754-2008 semantics for minNum, except for handling of
225/// signaling NaNs; this function handles all NaNs the same way and avoids
226/// minNum's problems with associativity. This also matches the behavior of
227/// libm’s fmin.
228///
229/// # Examples
230///
231/// ```rune
232/// let x = 1.0_f64;
233/// let y = 2.0_f64;
234///
235/// assert_eq!(x.min(y), x);
236/// ```
237#[rune::function(keep, instance, protocol = MIN)]
238fn min(this: f64, other: f64) -> f64 {
239    this.min(other)
240}
241
242/// Returns the square root of a number.
243///
244/// Returns NaN if `self` is a negative number other than `-0.0`.
245///
246/// # Examples
247///
248/// ```rune
249/// let positive = 4.0_f64;
250/// let negative = -4.0_f64;
251/// let negative_zero = -0.0_f64;
252///
253/// let abs_difference = (positive.sqrt() - 2.0).abs();
254///
255/// assert!(abs_difference < 1e-10);
256/// assert!(negative.sqrt().is_nan());
257/// assert!(negative_zero.sqrt() == negative_zero);
258/// ```
259#[rune::function(instance)]
260#[cfg(feature = "std")]
261fn sqrt(this: f64) -> f64 {
262    this.sqrt()
263}
264
265/// Computes the absolute value of `self`.
266///
267/// # Examples
268///
269/// ```rune
270/// let x = 3.5_f64;
271/// let y = -3.5_f64;
272///
273/// let abs_difference_x = (x.abs() - x).abs();
274/// let abs_difference_y = (y.abs() - (-y)).abs();
275///
276/// assert!(abs_difference_x < 1e-10);
277/// assert!(abs_difference_y < 1e-10);
278///
279/// assert!(f64::NAN.abs().is_nan());
280/// ```
281#[rune::function(instance)]
282#[cfg(feature = "std")]
283fn abs(this: f64) -> f64 {
284    this.abs()
285}
286
287/// Raises a number to a floating point power.
288///
289/// # Examples
290///
291/// ```rune
292/// let x = 2.0_f64;
293/// let abs_difference = (x.powf(2.0) - (x * x)).abs();
294///
295/// assert!(abs_difference < 1e-10);
296/// ```
297#[rune::function(instance)]
298#[cfg(feature = "std")]
299fn powf(this: f64, other: f64) -> f64 {
300    this.powf(other)
301}
302
303/// Raises a number to an integer power.
304///
305/// Using this function is generally faster than using `powf`. It might have a
306/// different sequence of rounding operations than `powf`, so the results are
307/// not guaranteed to agree.
308///
309/// # Examples
310///
311/// ```rune
312/// let x = 2.0_f64;
313/// let abs_difference = (x.powi(2) - (x * x)).abs();
314///
315/// assert!(abs_difference < 1e-10);
316/// ```
317#[rune::function(instance)]
318#[cfg(feature = "std")]
319fn powi(this: f64, other: i32) -> f64 {
320    this.powi(other)
321}
322
323/// Returns the largest integer less than or equal to `self`.
324///
325/// # Examples
326///
327/// ```rune
328/// let f = 3.7_f64;
329/// let g = 3.0_f64;
330/// let h = -3.7_f64;
331///
332/// assert!(f.floor() == 3.0);
333/// assert!(g.floor() == 3.0);
334/// assert!(h.floor() == -4.0);
335/// ```
336#[rune::function(instance)]
337#[cfg(feature = "std")]
338fn floor(this: f64) -> f64 {
339    this.floor()
340}
341
342/// Returns the smallest integer greater than or equal to `self`.
343///
344/// # Examples
345///
346/// ```rune
347/// let f = 3.01_f64;
348/// let g = 4.0_f64;
349///
350/// assert_eq!(f.ceil(), 4.0);
351/// assert_eq!(g.ceil(), 4.0);
352/// ```
353#[rune::function(instance)]
354#[cfg(feature = "std")]
355fn ceil(this: f64) -> f64 {
356    this.ceil()
357}
358
359/// Returns the nearest integer to `self`. If a value is half-way between two
360/// integers, round away from `0.0`.
361///
362/// # Examples
363///
364/// ```rune
365/// let f = 3.3_f64;
366/// let g = -3.3_f64;
367/// let h = -3.7_f64;
368/// let i = 3.5_f64;
369/// let j = 4.5_f64;
370///
371/// assert_eq!(f.round(), 3.0);
372/// assert_eq!(g.round(), -3.0);
373/// assert_eq!(h.round(), -4.0);
374/// assert_eq!(i.round(), 4.0);
375/// assert_eq!(j.round(), 5.0);
376/// ```
377#[rune::function(instance)]
378#[cfg(feature = "std")]
379fn round(this: f64) -> f64 {
380    this.round()
381}
382
383/// Clone a `f64`.
384///
385/// Note that since the type is copy, cloning has the same effect as assigning
386/// it.
387///
388/// # Examples
389///
390/// ```rune
391/// let a = 5.0;
392/// let b = a;
393/// let c = a.clone();
394///
395/// a += 1.0;
396///
397/// assert_eq!(a, 6.0);
398/// assert_eq!(b, 5.0);
399/// assert_eq!(c, 5.0);
400/// ```
401#[rune::function(keep, instance, protocol = CLONE)]
402#[inline]
403fn clone(this: f64) -> f64 {
404    this
405}
406
407/// Test two floats for partial equality.
408///
409/// # Examples
410///
411/// ```rune
412/// assert!(5.0 == 5.0);
413/// assert!(5.0 != 10.0);
414/// assert!(10.0 != 5.0);
415/// assert!(10.0 != f64::NAN);
416/// assert!(f64::NAN != f64::NAN);
417/// ```
418#[rune::function(keep, instance, protocol = PARTIAL_EQ)]
419#[inline]
420fn partial_eq(this: f64, rhs: f64) -> bool {
421    this.eq(&rhs)
422}
423
424/// Test two floats for total equality.
425///
426/// # Examples
427///
428/// ```rune
429/// use std::ops::eq;
430///
431/// assert_eq!(eq(5.0, 5.0), true);
432/// assert_eq!(eq(5.0, 10.0), false);
433/// assert_eq!(eq(10.0, 5.0), false);
434/// ```
435#[rune::function(keep, instance, protocol = EQ)]
436#[inline]
437fn eq(this: f64, rhs: f64) -> VmResult<bool> {
438    let Some(ordering) = this.partial_cmp(&rhs) else {
439        return VmResult::err(VmErrorKind::IllegalFloatComparison { lhs: this, rhs });
440    };
441
442    VmResult::Ok(matches!(ordering, Ordering::Equal))
443}
444
445/// Perform a partial ordered comparison between two floats.
446///
447/// # Examples
448///
449/// ```rune
450/// use std::cmp::Ordering;
451/// use std::ops::partial_cmp;
452///
453/// assert_eq!(partial_cmp(5.0, 10.0), Some(Ordering::Less));
454/// assert_eq!(partial_cmp(10.0, 5.0), Some(Ordering::Greater));
455/// assert_eq!(partial_cmp(5.0, 5.0), Some(Ordering::Equal));
456/// assert_eq!(partial_cmp(5.0, f64::NAN), None);
457/// ```
458#[rune::function(keep, instance, protocol = PARTIAL_CMP)]
459#[inline]
460fn partial_cmp(this: f64, rhs: f64) -> Option<Ordering> {
461    this.partial_cmp(&rhs)
462}
463
464/// Perform a totally ordered comparison between two floats.
465///
466/// # Examples
467///
468/// ```rune
469/// use std::cmp::Ordering;
470/// use std::ops::cmp;
471///
472/// assert_eq!(cmp(5.0, 10.0), Ordering::Less);
473/// assert_eq!(cmp(10.0, 5.0), Ordering::Greater);
474/// assert_eq!(cmp(5.0, 5.0), Ordering::Equal);
475/// ```
476#[rune::function(keep, instance, protocol = CMP)]
477#[inline]
478fn cmp(this: f64, rhs: f64) -> VmResult<Ordering> {
479    let Some(ordering) = this.partial_cmp(&rhs) else {
480        return VmResult::err(VmErrorKind::IllegalFloatComparison { lhs: this, rhs });
481    };
482
483    VmResult::Ok(ordering)
484}