1 | // Licensed to the .NET Foundation under one or more agreements. |
2 | // The .NET Foundation licenses this file to you under the MIT license. |
3 | // See the LICENSE file in the project root for more information. |
4 | // |
5 | // File: FloatDouble.cpp |
6 | // |
7 | |
8 | #include <common.h> |
9 | |
10 | #include "floatdouble.h" |
11 | |
12 | // The default compilation mode is /fp:precise, which disables floating-point intrinsics. This |
13 | // default compilation mode has previously caused performance regressions in floating-point code. |
14 | // We enable /fp:fast semantics for the majority of the math functions, as it will speed up performance |
15 | // and is really unlikely to cause any other code regressions. |
16 | |
17 | // Sin, Cos, and Tan on AMD64 Windows were previously implemented in vm\amd64\JitHelpers_Fast.asm |
18 | // by calling x87 floating point code (fsin, fcos, fptan) because the CRT helpers were too slow. This |
19 | // is no longer the case and the CRT call is used on all platforms. |
20 | |
21 | // Log, Log10 and Exp were previously slower with /fp:fast on SSE2 enabled hardware (see #500373). |
22 | // This is no longer the case and they now consume use the /fp:fast versions. |
23 | |
24 | // Exp(+/-INFINITY) did not previously return the expected results of +0.0 (for -INFINITY) |
25 | // and +INFINITY (for +INFINITY) so these cases were handled specially. As this is no longer |
26 | // the case and the expected results are now returned, the special handling has been removed. |
27 | |
28 | // Previously there was more special handling for the x86 Windows version of Pow. |
29 | // This additional handling was unnecessary and has since been removed. |
30 | |
31 | //////////////////////////////////////////////////////////////////////////////////// |
32 | //////////////////////////////////////////////////////////////////////////////////// |
33 | //////////////////////////////////////////////////////////////////////////////////// |
34 | /// |
35 | /// beginning of /fp:fast scope |
36 | /// |
37 | //////////////////////////////////////////////////////////////////////////////////// |
38 | //////////////////////////////////////////////////////////////////////////////////// |
39 | //////////////////////////////////////////////////////////////////////////////////// |
40 | |
41 | #ifdef _MSC_VER |
42 | #pragma float_control(push) |
43 | #pragma float_control(precise, off) |
44 | #endif |
45 | |
46 | /*=====================================Abs====================================== |
47 | ** |
48 | ==============================================================================*/ |
49 | FCIMPL1_V(double, COMDouble::Abs, double x) |
50 | FCALL_CONTRACT; |
51 | |
52 | return (double)fabs(x); |
53 | FCIMPLEND |
54 | |
55 | /*=====================================Acos===================================== |
56 | ** |
57 | ==============================================================================*/ |
58 | FCIMPL1_V(double, COMDouble::Acos, double x) |
59 | FCALL_CONTRACT; |
60 | |
61 | return (double)acos(x); |
62 | FCIMPLEND |
63 | |
64 | /*=====================================Acosh==================================== |
65 | ** |
66 | ==============================================================================*/ |
67 | FCIMPL1_V(double, COMDouble::Acosh, double x) |
68 | FCALL_CONTRACT; |
69 | |
70 | return (double)acosh(x); |
71 | FCIMPLEND |
72 | |
73 | /*=====================================Asin===================================== |
74 | ** |
75 | ==============================================================================*/ |
76 | FCIMPL1_V(double, COMDouble::Asin, double x) |
77 | FCALL_CONTRACT; |
78 | |
79 | return (double)asin(x); |
80 | FCIMPLEND |
81 | |
82 | /*=====================================Asinh==================================== |
83 | ** |
84 | ==============================================================================*/ |
85 | FCIMPL1_V(double, COMDouble::Asinh, double x) |
86 | FCALL_CONTRACT; |
87 | |
88 | return (double)asinh(x); |
89 | FCIMPLEND |
90 | |
91 | /*=====================================Atan===================================== |
92 | ** |
93 | ==============================================================================*/ |
94 | FCIMPL1_V(double, COMDouble::Atan, double x) |
95 | FCALL_CONTRACT; |
96 | |
97 | return (double)atan(x); |
98 | FCIMPLEND |
99 | |
100 | /*=====================================Atanh==================================== |
101 | ** |
102 | ==============================================================================*/ |
103 | FCIMPL1_V(double, COMDouble::Atanh, double x) |
104 | FCALL_CONTRACT; |
105 | |
106 | return (double)atanh(x); |
107 | FCIMPLEND |
108 | |
109 | /*=====================================Atan2==================================== |
110 | ** |
111 | ==============================================================================*/ |
112 | FCIMPL2_VV(double, COMDouble::Atan2, double y, double x) |
113 | FCALL_CONTRACT; |
114 | |
115 | return (double)atan2(y, x); |
116 | FCIMPLEND |
117 | |
118 | /*====================================Cbrt====================================== |
119 | ** |
120 | ==============================================================================*/ |
121 | FCIMPL1_V(double, COMDouble::Cbrt, double x) |
122 | FCALL_CONTRACT; |
123 | |
124 | return (double)cbrt(x); |
125 | FCIMPLEND |
126 | |
127 | #if defined(_MSC_VER) && defined(_TARGET_AMD64_) |
128 | // The /fp:fast form of `ceil` for AMD64 does not correctly handle: `-1.0 < value <= -0.0` |
129 | // https://github.com/dotnet/coreclr/issues/19739 |
130 | #pragma float_control(push) |
131 | #pragma float_control(precise, on) |
132 | #endif |
133 | |
134 | /*====================================Ceil====================================== |
135 | ** |
136 | ==============================================================================*/ |
137 | FCIMPL1_V(double, COMDouble::Ceil, double x) |
138 | FCALL_CONTRACT; |
139 | |
140 | return (double)ceil(x); |
141 | FCIMPLEND |
142 | |
143 | #if defined(_MSC_VER) && defined(_TARGET_AMD64_) |
144 | #pragma float_control(pop) |
145 | #endif |
146 | |
147 | /*=====================================Cos====================================== |
148 | ** |
149 | ==============================================================================*/ |
150 | FCIMPL1_V(double, COMDouble::Cos, double x) |
151 | FCALL_CONTRACT; |
152 | |
153 | return (double)cos(x); |
154 | FCIMPLEND |
155 | |
156 | /*=====================================Cosh===================================== |
157 | ** |
158 | ==============================================================================*/ |
159 | FCIMPL1_V(double, COMDouble::Cosh, double x) |
160 | FCALL_CONTRACT; |
161 | |
162 | return (double)cosh(x); |
163 | FCIMPLEND |
164 | |
165 | /*=====================================Exp====================================== |
166 | ** |
167 | ==============================================================================*/ |
168 | FCIMPL1_V(double, COMDouble::Exp, double x) |
169 | FCALL_CONTRACT; |
170 | |
171 | return (double)exp(x); |
172 | FCIMPLEND |
173 | |
174 | #if defined(_MSC_VER) && defined(_TARGET_X86_) |
175 | // The /fp:fast form of `floor` for x86 does not correctly handle: `-0.0` |
176 | // https://github.com/dotnet/coreclr/issues/19739 |
177 | #pragma float_control(push) |
178 | #pragma float_control(precise, on) |
179 | #endif |
180 | |
181 | /*====================================Floor===================================== |
182 | ** |
183 | ==============================================================================*/ |
184 | FCIMPL1_V(double, COMDouble::Floor, double x) |
185 | FCALL_CONTRACT; |
186 | |
187 | return (double)floor(x); |
188 | FCIMPLEND |
189 | |
190 | #if defined(_MSC_VER) && defined(_TARGET_X86_) |
191 | #pragma float_control(pop) |
192 | #endif |
193 | |
194 | /*=====================================FMod===================================== |
195 | ** |
196 | ==============================================================================*/ |
197 | FCIMPL2_VV(double, COMDouble::FMod, double x, double y) |
198 | FCALL_CONTRACT; |
199 | |
200 | return (double)fmod(x, y); |
201 | FCIMPLEND |
202 | |
203 | /*=====================================FusedMultiplyAdd========================== |
204 | ** |
205 | ==============================================================================*/ |
206 | FCIMPL3_VVV(double, COMDouble::FusedMultiplyAdd, double x, double y, double z) |
207 | FCALL_CONTRACT; |
208 | |
209 | return (double)fma(x, y, z); |
210 | FCIMPLEND |
211 | |
212 | /*=====================================Ilog2==================================== |
213 | ** |
214 | ==============================================================================*/ |
215 | FCIMPL1_V(int, COMDouble::ILogB, double x) |
216 | FCALL_CONTRACT; |
217 | |
218 | return (int)ilogb(x); |
219 | FCIMPLEND |
220 | |
221 | /*=====================================Log====================================== |
222 | ** |
223 | ==============================================================================*/ |
224 | FCIMPL1_V(double, COMDouble::Log, double x) |
225 | FCALL_CONTRACT; |
226 | |
227 | return (double)log(x); |
228 | FCIMPLEND |
229 | |
230 | /*=====================================Log2===================================== |
231 | ** |
232 | ==============================================================================*/ |
233 | FCIMPL1_V(double, COMDouble::Log2, double x) |
234 | FCALL_CONTRACT; |
235 | |
236 | return (double)log2(x); |
237 | FCIMPLEND |
238 | |
239 | /*====================================Log10===================================== |
240 | ** |
241 | ==============================================================================*/ |
242 | FCIMPL1_V(double, COMDouble::Log10, double x) |
243 | FCALL_CONTRACT; |
244 | |
245 | return (double)log10(x); |
246 | FCIMPLEND |
247 | |
248 | /*=====================================ModF===================================== |
249 | ** |
250 | ==============================================================================*/ |
251 | FCIMPL2_VI(double, COMDouble::ModF, double x, double* intptr) |
252 | FCALL_CONTRACT; |
253 | |
254 | return (double)modf(x, intptr); |
255 | FCIMPLEND |
256 | |
257 | /*=====================================Pow====================================== |
258 | ** |
259 | ==============================================================================*/ |
260 | FCIMPL2_VV(double, COMDouble::Pow, double x, double y) |
261 | FCALL_CONTRACT; |
262 | |
263 | return (double)pow(x, y); |
264 | FCIMPLEND |
265 | |
266 | /*=====================================ScaleB=================================== |
267 | ** |
268 | ==============================================================================*/ |
269 | FCIMPL2_VI(double, COMDouble::ScaleB, double x, int n) |
270 | FCALL_CONTRACT; |
271 | |
272 | return (double)scalbn(x, n); |
273 | FCIMPLEND |
274 | |
275 | /*=====================================Sin====================================== |
276 | ** |
277 | ==============================================================================*/ |
278 | FCIMPL1_V(double, COMDouble::Sin, double x) |
279 | FCALL_CONTRACT; |
280 | |
281 | return (double)sin(x); |
282 | FCIMPLEND |
283 | |
284 | /*=====================================Sinh===================================== |
285 | ** |
286 | ==============================================================================*/ |
287 | FCIMPL1_V(double, COMDouble::Sinh, double x) |
288 | FCALL_CONTRACT; |
289 | |
290 | return (double)sinh(x); |
291 | FCIMPLEND |
292 | |
293 | /*=====================================Sqrt===================================== |
294 | ** |
295 | ==============================================================================*/ |
296 | FCIMPL1_V(double, COMDouble::Sqrt, double x) |
297 | FCALL_CONTRACT; |
298 | |
299 | return (double)sqrt(x); |
300 | FCIMPLEND |
301 | |
302 | /*=====================================Tan====================================== |
303 | ** |
304 | ==============================================================================*/ |
305 | FCIMPL1_V(double, COMDouble::Tan, double x) |
306 | FCALL_CONTRACT; |
307 | |
308 | return (double)tan(x); |
309 | FCIMPLEND |
310 | |
311 | /*=====================================Tanh===================================== |
312 | ** |
313 | ==============================================================================*/ |
314 | FCIMPL1_V(double, COMDouble::Tanh, double x) |
315 | FCALL_CONTRACT; |
316 | |
317 | return (double)tanh(x); |
318 | FCIMPLEND |
319 | |
320 | #ifdef _MSC_VER |
321 | #pragma float_control(pop) |
322 | #endif |
323 | |
324 | //////////////////////////////////////////////////////////////////////////////////// |
325 | //////////////////////////////////////////////////////////////////////////////////// |
326 | //////////////////////////////////////////////////////////////////////////////////// |
327 | /// |
328 | /// End of /fp:fast scope |
329 | /// |
330 | //////////////////////////////////////////////////////////////////////////////////// |
331 | //////////////////////////////////////////////////////////////////////////////////// |
332 | //////////////////////////////////////////////////////////////////////////////////// |
333 | |