/src/r-source/src/nmath/cospi.c
Line | Count | Source |
1 | | /* |
2 | | * Mathlib : A C Library of Special Functions |
3 | | * Copyright (C) 2013-2022 The R Core Team |
4 | | * |
5 | | * This program is free software; you can redistribute it and/or modify |
6 | | * it under the terms of the GNU General Public License as published by |
7 | | * the Free Software Foundation; either version 2 of the License, or |
8 | | * (at your option) any later version. |
9 | | * |
10 | | * This program is distributed in the hope that it will be useful, |
11 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | | * GNU General Public License for more details. |
14 | | */ |
15 | | |
16 | | #include "nmath.h" |
17 | | |
18 | | /* HAVE_COSPI etc will not be defined in standalone-use: the |
19 | | intention is to make the versions here available in that case. |
20 | | |
21 | | The __cospi etc variants are from macOS (and perhaps other BSD-based systems). |
22 | | */ |
23 | | |
24 | | #ifdef HAVE_COSPI |
25 | | #elif defined HAVE___COSPI |
26 | | double cospi(double x) { |
27 | | return __cospi(x); |
28 | | } |
29 | | #else |
30 | | // cos(pi * x) -- exact when x = k/2 for all integer k |
31 | 0 | double cospi(double x) { |
32 | 0 | #ifdef IEEE_754 |
33 | | /* NaNs propagated correctly */ |
34 | 0 | if (ISNAN(x)) return x; |
35 | 0 | #endif |
36 | 0 | if(!R_FINITE(x)) ML_WARN_return_NAN; |
37 | |
|
38 | 0 | x = fmod(fabs(x), 2.);// cos() symmetric; cos(pi(x + 2k)) == cos(pi x) for all integer k |
39 | 0 | if(fmod(x, 1.) == 0.5) return 0.; |
40 | 0 | if( x == 1.) return -1.; |
41 | 0 | if( x == 0.) return 1.; |
42 | | // otherwise |
43 | 0 | return cos(M_PI * x); |
44 | 0 | } |
45 | | #endif |
46 | | |
47 | | #ifdef HAVE_SINPI |
48 | | #elif defined HAVE___SINPI |
49 | | double sinpi(double x) { |
50 | | return __sinpi(x); |
51 | | } |
52 | | #else |
53 | | // sin(pi * x) -- exact when x = k/2 for all integer k |
54 | 0 | double sinpi(double x) { |
55 | 0 | #ifdef IEEE_754 |
56 | 0 | if (ISNAN(x)) return x; |
57 | 0 | #endif |
58 | 0 | if(!R_FINITE(x)) ML_WARN_return_NAN; |
59 | |
|
60 | 0 | x = fmod(x, 2.); // sin(pi(x + 2k)) == sin(pi x) for all integer k |
61 | | // map (-2,2) --> (-1,1] : |
62 | 0 | if(x <= -1) x += 2.; else if (x > 1.) x -= 2.; |
63 | 0 | if(x == 0. || x == 1.) return 0.; |
64 | 0 | if(x == 0.5) return 1.; |
65 | 0 | if(x == -0.5) return -1.; |
66 | | // otherwise |
67 | 0 | return sin(M_PI * x); |
68 | 0 | } |
69 | | #endif |
70 | | |
71 | | // tan(pi * x) -- exact when x = k/4 for all integer k and half-values give NaN |
72 | | // ----------- e.g. used in ../main/arithmetic.c : |
73 | | double Rtanpi(double x) |
74 | 0 | { |
75 | 0 | #ifdef IEEE_754 |
76 | 0 | if (ISNAN(x)) return x; |
77 | 0 | #endif |
78 | 0 | if(!R_FINITE(x)) ML_WARN_return_NAN; |
79 | |
|
80 | 0 | x = fmod(x, 1.); // tan(pi(x + k)) == tan(pi x) for all integer k |
81 | | // map (-1,1] --> (-1/2, 1/2] : |
82 | 0 | if(x <= -0.5) x++; else if(x > 0.5) x--; |
83 | 0 | return (x == 0.) ? 0. : |
84 | 0 | ((x == 0.5 ) ? ML_NAN : |
85 | 0 | ((x == 0.25) ? 1. : |
86 | 0 | ((x == -0.25) ? -1. : |
87 | 0 | tan(M_PI * x) |
88 | 0 | ))); |
89 | 0 | } |
90 | | |
91 | | #if defined(HAVE_TANPI) || defined(HAVE___TANPI) |
92 | | #else |
93 | 0 | double tanpi(double x) { |
94 | 0 | return Rtanpi(x); |
95 | 0 | } |
96 | | #endif |
97 | | |
98 | | #if !defined(HAVE_TANPI) && defined(HAVE___TANPI) |
99 | | double tanpi(double x) { |
100 | | return __tanpi(x); |
101 | | } |
102 | | /* #else tanpi() defined from C standard math lib */ |
103 | | #endif |