| 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 | |