1 use core::marker::PhantomData;
2 
3 use crate::*;
4 
5 /// Generic helper for libm functions, abstracting over f32 and f64. <br/>
6 /// # Type Parameter:
7 /// - `T`: Either `f32` or `f64`
8 ///
9 /// # Examples
10 /// ```rust
11 /// use libm::{self, Libm};
12 ///
13 /// const PI_F32: f32 = 3.1415927410e+00;
14 /// const PI_F64: f64 = 3.1415926535897931160e+00;
15 ///
16 /// assert!(Libm::<f32>::cos(0.0f32) == libm::cosf(0.0));
17 /// assert!(Libm::<f32>::sin(PI_F32) == libm::sinf(PI_F32));
18 ///
19 /// assert!(Libm::<f64>::cos(0.0f64) == libm::cos(0.0));
20 /// assert!(Libm::<f64>::sin(PI_F64) == libm::sin(PI_F64));
21 /// ```
22 pub struct Libm<T>(PhantomData<T>);
23 
24 macro_rules! libm_helper {
25     ($t:ident, funcs: $funcs:tt) => {
26         impl Libm<$t> {
27             #![allow(unused_parens)]
28 
29             libm_helper! { $funcs }
30         }
31     };
32 
33     ({$($func:tt);*}) => {
34         $(
35             libm_helper! { $func }
36         )*
37     };
38 
39     ((fn $func:ident($($arg:ident: $arg_typ:ty),*) -> ($($ret_typ:ty),*); => $libm_fn:ident)) => {
40         #[inline(always)]
41         pub fn $func($($arg: $arg_typ),*) -> ($($ret_typ),*) {
42             $libm_fn($($arg),*)
43         }
44     };
45 }
46 
47 libm_helper! {
48     f32,
49     funcs: {
50         (fn acos(x: f32) -> (f32);                  => acosf);
51         (fn acosh(x: f32) -> (f32);                 => acoshf);
52         (fn asin(x: f32) -> (f32);                  => asinf);
53         (fn asinh(x: f32) -> (f32);                 => asinhf);
54         (fn atan(x: f32) -> (f32);                  => atanf);
55         (fn atan2(y: f32, x: f32) -> (f32);         => atan2f);
56         (fn atanh(x: f32) -> (f32);                 => atanhf);
57         (fn cbrt(x: f32) -> (f32);                  => cbrtf);
58         (fn ceil(x: f32) -> (f32);                  => ceilf);
59         (fn copysign(x: f32, y: f32) -> (f32);      => copysignf);
60         (fn cos(x: f32) -> (f32);                   => cosf);
61         (fn cosh(x: f32) -> (f32);                  => coshf);
62         (fn erf(x: f32) -> (f32);                   => erff);
63         (fn erfc(x: f32) -> (f32);                  => erfcf);
64         (fn exp(x: f32) -> (f32);                   => expf);
65         (fn exp2(x: f32) -> (f32);                  => exp2f);
66         (fn exp10(x: f32) -> (f32);                 => exp10f);
67         (fn expm1(x: f32) -> (f32);                 => expm1f);
68         (fn fabs(x: f32) -> (f32);                  => fabsf);
69         (fn fdim(x: f32, y: f32) -> (f32);          => fdimf);
70         (fn floor(x: f32) -> (f32);                 => floorf);
71         (fn fma(x: f32, y: f32, z: f32) -> (f32);   => fmaf);
72         (fn fmax(x: f32, y: f32) -> (f32);          => fmaxf);
73         (fn fmin(x: f32, y: f32) -> (f32);          => fminf);
74         (fn fmod(x: f32, y: f32) -> (f32);          => fmodf);
75         (fn frexp(x: f32) -> (f32, i32);            => frexpf);
76         (fn hypot(x: f32, y: f32) -> (f32);         => hypotf);
77         (fn ilogb(x: f32) -> (i32);                 => ilogbf);
78         (fn j0(x: f32) -> (f32);                    => j0f);
79         (fn j1(x: f32) -> (f32);                    => j1f);
80         (fn jn(n: i32, x: f32) -> (f32);            => jnf);
81         (fn ldexp(x: f32, n: i32) -> (f32);         => ldexpf);
82         (fn lgamma_r(x: f32) -> (f32, i32);         => lgammaf_r);
83         (fn lgamma(x: f32) -> (f32);                => lgammaf);
84         (fn log(x: f32) -> (f32);                   => logf);
85         (fn log1p(x: f32) -> (f32);                 => log1pf);
86         (fn log2(x: f32) -> (f32);                  => log2f);
87         (fn log10(x: f32) -> (f32);                 => log10f);
88         (fn modf(x: f32) -> (f32, f32);             => modff);
89         (fn nextafter(x: f32, y: f32) -> (f32);     => nextafterf);
90         (fn pow(x: f32, y: f32) -> (f32);           => powf);
91         (fn remainder(x: f32, y: f32) -> (f32);     => remainderf);
92         (fn remquo(x: f32, y: f32) -> (f32, i32);   => remquof);
93         (fn rint(x: f32) -> (f32);                  => rintf);
94         (fn round(x: f32) -> (f32);                 => roundf);
95         (fn scalbn(x: f32, n: i32) -> (f32);        => scalbnf);
96         (fn sin(x: f32) -> (f32);                   => sinf);
97         (fn sincos(x: f32) -> (f32, f32);           => sincosf);
98         (fn sinh(x: f32) -> (f32);                  => sinhf);
99         (fn sqrt(x: f32) -> (f32);                  => sqrtf);
100         (fn tan(x: f32) -> (f32);                   => tanf);
101         (fn tanh(x: f32) -> (f32);                  => tanhf);
102         (fn tgamma(x: f32) -> (f32);                => tgammaf);
103         (fn trunc(x: f32) -> (f32);                 => truncf);
104         (fn y0(x: f32) -> (f32);                    => y0f);
105         (fn y1(x: f32) -> (f32);                    => y1f);
106         (fn yn(n: i32, x: f32) -> (f32);            => ynf)
107     }
108 }
109 
110 libm_helper! {
111     f64,
112     funcs: {
113         (fn acos(x: f64) -> (f64);                  => acos);
114         (fn acosh(x: f64) -> (f64);                 => acosh);
115         (fn asin(x: f64) -> (f64);                  => asin);
116         (fn asinh(x: f64) -> (f64);                 => asinh);
117         (fn atan(x: f64) -> (f64);                  => atan);
118         (fn atan2(y: f64, x: f64) -> (f64);         => atan2);
119         (fn atanh(x: f64) -> (f64);                 => atanh);
120         (fn cbrt(x: f64) -> (f64);                  => cbrt);
121         (fn ceil(x: f64) -> (f64);                  => ceil);
122         (fn copysign(x: f64, y: f64) -> (f64);      => copysign);
123         (fn cos(x: f64) -> (f64);                   => cos);
124         (fn cosh(x: f64) -> (f64);                  => cosh);
125         (fn erf(x: f64) -> (f64);                   => erf);
126         (fn erfc(x: f64) -> (f64);                  => erfc);
127         (fn exp(x: f64) -> (f64);                   => exp);
128         (fn exp2(x: f64) -> (f64);                  => exp2);
129         (fn exp10(x: f64) -> (f64);                 => exp10);
130         (fn expm1(x: f64) -> (f64);                 => expm1);
131         (fn fabs(x: f64) -> (f64);                  => fabs);
132         (fn fdim(x: f64, y: f64) -> (f64);          => fdim);
133         (fn floor(x: f64) -> (f64);                 => floor);
134         (fn fma(x: f64, y: f64, z: f64) -> (f64);   => fma);
135         (fn fmax(x: f64, y: f64) -> (f64);          => fmax);
136         (fn fmin(x: f64, y: f64) -> (f64);          => fmin);
137         (fn fmod(x: f64, y: f64) -> (f64);          => fmod);
138         (fn frexp(x: f64) -> (f64, i32);            => frexp);
139         (fn hypot(x: f64, y: f64) -> (f64);         => hypot);
140         (fn ilogb(x: f64) -> (i32);                 => ilogb);
141         (fn j0(x: f64) -> (f64);                    => j0);
142         (fn j1(x: f64) -> (f64);                    => j1);
143         (fn jn(n: i32, x: f64) -> (f64);            => jn);
144         (fn ldexp(x: f64, n: i32) -> (f64);         => ldexp);
145         (fn lgamma_r(x: f64) -> (f64, i32);         => lgamma_r);
146         (fn lgamma(x: f64) -> (f64);                => lgamma);
147         (fn log(x: f64) -> (f64);                   => log);
148         (fn log1p(x: f64) -> (f64);                 => log1p);
149         (fn log2(x: f64) -> (f64);                  => log2);
150         (fn log10(x: f64) -> (f64);                 => log10);
151         (fn modf(x: f64) -> (f64, f64);             => modf);
152         (fn nextafter(x: f64, y: f64) -> (f64);     => nextafter);
153         (fn pow(x: f64, y: f64) -> (f64);           => pow);
154         (fn remainder(x: f64, y: f64) -> (f64);     => remainder);
155         (fn remquo(x: f64, y: f64) -> (f64, i32);   => remquo);
156         (fn rint(x: f64) -> (f64);                  => rint);
157         (fn round(x: f64) -> (f64);                 => round);
158         (fn scalbn(x: f64, n: i32) -> (f64);        => scalbn);
159         (fn sin(x: f64) -> (f64);                   => sin);
160         (fn sincos(x: f64) -> (f64, f64);           => sincos);
161         (fn sinh(x: f64) -> (f64);                  => sinh);
162         (fn sqrt(x: f64) -> (f64);                  => sqrt);
163         (fn tan(x: f64) -> (f64);                   => tan);
164         (fn tanh(x: f64) -> (f64);                  => tanh);
165         (fn tgamma(x: f64) -> (f64);                => tgamma);
166         (fn trunc(x: f64) -> (f64);                 => trunc);
167         (fn y0(x: f64) -> (f64);                    => y0);
168         (fn y1(x: f64) -> (f64);                    => y1);
169         (fn yn(n: i32, x: f64) -> (f64);            => yn)
170     }
171 }
172