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}