float_extras/
lib.rs

1extern crate libc;
2
3#[allow(dead_code)]
4mod cmath {
5    use libc::{c_double, c_int};
6
7    #[link_name = "m"]
8    extern "C" {
9        pub fn frexp(n: c_double, value: &mut c_int) -> c_double;
10        pub fn ldexp(x: c_double, n: c_int) -> c_double;
11        pub fn modf(x: c_double, iptr: &mut c_double) -> c_double;
12        pub fn ilogb(n: c_double) -> c_int;
13        pub fn logb(n: c_double) -> c_double;
14        pub fn scalbn(x: c_double, n: c_int) -> c_double;
15
16        pub fn erf(n: c_double) -> c_double;
17        pub fn erfc(n: c_double) -> c_double;
18        pub fn tgamma(n: c_double) -> c_double;
19        pub fn lgamma(n: c_double) -> c_double;
20
21        pub fn fmod(a: c_double, b: c_double) -> c_double;
22        pub fn lround(x: c_double) -> c_int;
23        // need longlong: llround
24        // need fenv.h: rint, lrint, llrint, nearbyint
25        pub fn remainder(a: c_double, b: c_double) -> c_double;
26        pub fn remquo(x: c_double, y: c_double, quot: &mut c_int) -> c_double;
27
28        pub fn copysign(x: c_double, y: c_double) -> c_double;
29        pub fn nextafter(x: c_double, y: c_double) -> c_double;
30        // need long_double: nexttoward
31
32        pub fn fdim(a: c_double, b: c_double) -> c_double;
33        pub fn fma(x: c_double, y: c_double, z: c_double) -> c_double;
34    }
35}
36
37pub mod f64 {
38    use libc::c_int;
39    use super::cmath;
40
41    /// frexp is used to split the number x into a normalized fraction and an exponent
42    /// which is stored in exp.
43    pub fn frexp(x: f64) -> (f64, isize) {
44        let mut n: c_int = 0;
45        let f = unsafe { cmath::frexp(x, &mut n) };
46        (f, n as isize)
47    }
48    /// ldexp returns the result of multiplying the floating-point number x by 2 raised to
49    /// the power exp.
50    pub fn ldexp(x: f64, exp: isize) -> f64 {
51        unsafe { cmath::ldexp(x, exp as i32) }
52    }
53    /// modf breaks the argument x into an integral part and a fractional part, each
54    /// of which has the same sign as x.
55    pub fn modf(x: f64) -> (f64, f64) {
56        let mut i: f64 = 0.;
57        let f = unsafe { cmath::modf(x, &mut i) };
58        (i, f)
59    }
60    /// iligb returns the exponent part of their argument as a signed integer.
61    pub fn ilogb(n: f64) -> isize {
62        (unsafe { cmath::ilogb(n) }) as isize
63    }
64    /// logb extracts the exponent from the internal floating-point
65    /// representation of x and return it as a floating-point value.
66    pub fn logb(x: f64) -> f64 {
67        unsafe { cmath::logb(x) }
68    }
69    /// scalbn multiplies their first argument x by FLT_RADIX (probably 2) to the power of
70    /// exp, that is:
71    /// ```text
72    /// x * FLT_RADIX ** exp
73    /// ```
74    pub fn scalbn(x: f64, exp: isize) -> f64 {
75        unsafe { cmath::scalbn(x, exp as c_int) }
76    }
77
78    /// erf returns the error function of x, defined as
79    /// ```text
80    /// erf(x) = 2/sqrt(pi)* integral from 0 to x of exp(-t*t) dt
81    /// ```
82    pub fn erf(x: f64) -> f64 {
83        unsafe { cmath::erf(x) }
84    }
85    /// erfc returns the complementary error function of x, that is, 1.0 - erf(x).
86    pub fn erfc(x: f64) -> f64 {
87        unsafe { cmath::erfc(x) }
88    }
89
90    /// tgamma calculates the Gamma function of x.
91    ///
92    /// The Gamma function is defined by
93    ///
94    /// ```text
95    /// Gamma(x) = integral from 0 to infinity of t^(x-1) e^-t dt
96    /// ```
97    /// It is defined for every real number except for nonpositive integers.  For nonnegative
98    /// integral m one has
99    ///
100    /// ```text
101    /// Gamma(m+1) = m!
102    /// ```
103    /// and, more generally, for all x:
104    ///
105    /// ```text
106    /// Gamma(x+1) = x * Gamma(x)
107    /// ```
108    ///
109    /// Furthermore, the following is valid for all values of x outside the poles:
110    ///
111    /// ```text
112    /// Gamma(x) * Gamma(1 - x) = PI / sin(PI * x)
113    /// ```
114    pub fn tgamma(x: f64) -> f64 {
115        unsafe { cmath::tgamma(x) }
116    }
117    /// lgamma returns the natural logarithm of the absolute value of the Gamma function.
118    pub fn lgamma(x: f64) -> f64 {
119        unsafe { cmath::lgamma(x) }
120    }
121
122    /// fmod computes the floating-point remainder of dividing x by y.  The return
123    /// value is x - n * y, where n is the quotient of x / y, rounded toward zero to an integer.
124    pub fn fmod(x: f64, y: f64) -> f64 {
125        unsafe { cmath::fmod(x, y) }
126    }
127    /// lround rounds their argument to the nearest integer value, rounding away from zero.
128    pub fn lround(x: f64) -> isize {
129        (unsafe { cmath::lround(x) }) as isize
130    }
131    /// remainder compute the remainder of dividing x by y. The return value is x-n*y, where
132    /// n is the value x / y, rounded to the nearest integer. If the absolute value of x-n*y is
133    /// 0.5, n is chosen to be even.
134    pub fn remainder(x: f64, y: f64) -> f64 {
135        unsafe { cmath::remainder(x, y) }
136    }
137    /// remquo computes the remainder and part of the quotient upon division of x by y.
138    pub fn remquo(x: f64, y: f64) -> (isize, f64) {
139        let mut quot: c_int = 0;
140        let rem = unsafe { cmath::remquo(x, y, &mut quot) };
141        (quot as isize, rem)
142    }
143
144    /// copysign returns a value whose absolute value matches that of x, but whose sign bit
145    /// matches that of y.
146    pub fn copysign(x: f64, y: f64) -> f64 {
147        unsafe { cmath::copysign(x, y) }
148    }
149    /// nextafter returns the next representable floating-point value following x in the
150    /// direction of y. If y is less than x, these functions will return the largest representable
151    /// number less than x.
152    pub fn nextafter(x: f64, y: f64) -> f64 {
153        unsafe { cmath::nextafter(x, y) }
154    }
155
156    /// fdim returns the positive difference, max(x-y,0), between their arguments.
157    pub fn fdim(x: f64, y: f64) -> f64 {
158        unsafe { cmath::fdim(x, y) }
159    }
160    /// fma computes x * y + z. The result is rounded as one ternary operation
161    /// according to the current rounding mode.
162    pub fn fma(x: f64, y: f64, z: f64) -> f64 {
163        unsafe { cmath::fma(x, y, z) }
164    }
165}
166
167#[cfg(test)]
168mod tests {
169    use super::f64::*;
170
171    #[test]
172    fn smoke_test() {
173        frexp(0.);
174        ldexp(0., 0);
175        modf(0.);
176        ilogb(0.);
177        logb(0.);
178        scalbn(0., 0);
179
180        erf(0.);
181        erfc(0.);
182        tgamma(0.);
183        lgamma(0.);
184        lround(0.);
185        remainder(0., 0.);
186        remquo(0., 0.);
187
188        copysign(0., 0.);
189        nextafter(0., 0.);
190
191        fdim(0., 0.);
192        fma(0., 0., 0.);
193    }
194}