diff options
author | Tanner Gooding <tannergooding@users.noreply.github.com> | 2016-10-18 02:56:53 -0700 |
---|---|---|
committer | Jan Vorlicek <janvorli@microsoft.com> | 2016-10-18 11:56:53 +0200 |
commit | 6057b18d33216c3ee1436411e42e75a915a4714b (patch) | |
tree | 79f5282a27fbfb579763487a96c0e8f1bb56a9af /src/classlibnative | |
parent | bed314bb3005e3c5fc0b3c0723e398e702e08f65 (diff) | |
download | coreclr-6057b18d33216c3ee1436411e42e75a915a4714b.tar.gz coreclr-6057b18d33216c3ee1436411e42e75a915a4714b.tar.bz2 coreclr-6057b18d33216c3ee1436411e42e75a915a4714b.zip |
Adding single-precision math functions. (#5492)
* Adding single-precision math functions to floatsingle
* Adding single-precision math functions to the PAL layer.
* Adding single-precision math tests to the PAL layer.
* Adding single-precision math functions to mscorlib.
* Adding single-precision math function support to the vm.
* Updating floatsingle.cpp to define a _isnanf macro for Windows ARM.
Diffstat (limited to 'src/classlibnative')
-rw-r--r-- | src/classlibnative/float/floatsingle.cpp | 217 | ||||
-rw-r--r-- | src/classlibnative/inc/floatsingle.h | 19 |
2 files changed, 236 insertions, 0 deletions
diff --git a/src/classlibnative/float/floatsingle.cpp b/src/classlibnative/float/floatsingle.cpp index dd1bb43316..daf899921e 100644 --- a/src/classlibnative/float/floatsingle.cpp +++ b/src/classlibnative/float/floatsingle.cpp @@ -11,6 +11,11 @@ #define IS_FLT_INFINITY(x) (((*((INT32*)((void*)&x))) & 0x7FFFFFFF) == 0x7F800000) +// Windows x86 and Windows ARM don't define _isnanf() but they do define a generic macro isnan() +#if (defined(_TARGET_X86_) || defined(_TARGET_ARM_)) && !defined(FEATURE_PAL) && !defined(_isnanf) +#define _isnanf isnan +#endif + // The default compilation mode is /fp:precise, which disables floating-point intrinsics. This // default compilation mode has previously caused performance regressions in floating-point code. // We enable /fp:fast semantics for the majority of the math functions, as it will speed up performance @@ -39,6 +44,218 @@ FCIMPL1(float, COMSingle::Abs, float x) return (float)fabsf(x); FCIMPLEND +/*=====================================Acos===================================== +** +==============================================================================*/ +FCIMPL1(float, COMSingle::Acos, float x) + FCALL_CONTRACT; + + return (float)acosf(x); +FCIMPLEND + +/*=====================================Asin===================================== +** +==============================================================================*/ +FCIMPL1(float, COMSingle::Asin, float x) + FCALL_CONTRACT; + + return (float)asinf(x); +FCIMPLEND + +/*=====================================Atan===================================== +** +==============================================================================*/ +FCIMPL1(float, COMSingle::Atan, float x) + FCALL_CONTRACT; + + return (float)atanf(x); +FCIMPLEND + +/*=====================================Atan2==================================== +** +==============================================================================*/ +FCIMPL2(float, COMSingle::Atan2, float y, float x) + FCALL_CONTRACT; + + // atan2f(+/-INFINITY, +/-INFINITY) produces +/-0.785398163f (x is +INFINITY) and + // +/-2.35619449f (x is -INFINITY) instead of the expected value of NaN. We handle + // that case here ourselves. + if (IS_FLT_INFINITY(y) && IS_FLT_INFINITY(x)) { + return (float)(y / x); + } + + return (float)atan2f(y, x); +FCIMPLEND + +/*====================================Ceil====================================== +** +==============================================================================*/ +FCIMPL1(float, COMSingle::Ceil, float x) + FCALL_CONTRACT; + + return (float)ceilf(x); +FCIMPLEND + +/*=====================================Cos====================================== +** +==============================================================================*/ +FCIMPL1(float, COMSingle::Cos, float x) + FCALL_CONTRACT; + + return (float)cosf(x); +FCIMPLEND + +/*=====================================Cosh===================================== +** +==============================================================================*/ +FCIMPL1(float, COMSingle::Cosh, float x) + FCALL_CONTRACT; + + return (float)coshf(x); +FCIMPLEND + +/*=====================================Exp====================================== +** +==============================================================================*/ +FCIMPL1(float, COMSingle::Exp, float x) + FCALL_CONTRACT; + + return (float)expf(x); +FCIMPLEND + +/*====================================Floor===================================== +** +==============================================================================*/ +FCIMPL1(float, COMSingle::Floor, float x) + FCALL_CONTRACT; + + return (float)floorf(x); +FCIMPLEND + +/*=====================================Log====================================== +** +==============================================================================*/ +FCIMPL1(float, COMSingle::Log, float x) + FCALL_CONTRACT; + + return (float)logf(x); +FCIMPLEND + +/*====================================Log10===================================== +** +==============================================================================*/ +FCIMPL1(float, COMSingle::Log10, float x) + FCALL_CONTRACT; + + return (float)log10f(x); +FCIMPLEND + +/*=====================================ModF===================================== +** +==============================================================================*/ +FCIMPL1(float, COMSingle::ModF, float* iptr) + FCALL_CONTRACT; + + return (float)modff(*iptr, iptr); +FCIMPLEND + +/*=====================================Pow====================================== +** +==============================================================================*/ +FCIMPL2(float, COMSingle::Pow, float x, float y) + FCALL_CONTRACT; + + // The CRT version of pow preserves the NaN payload of x over the NaN payload of y. + + if(_isnanf(y)) { + return y; // IEEE 754-2008: NaN payload must be preserved + } + + if(_isnanf(x)) { + return x; // IEEE 754-2008: NaN payload must be preserved + } + + // The CRT version of powf does not return NaN for powf(-1.0f, +/-INFINITY) and + // instead returns +1.0f. + + if(IS_FLT_INFINITY(y) && (x == -1.0f)) { + INT32 result = CLR_NAN_32; + return (*((float*)((INT32*)&result))); + } + + return (float)powf(x, y); +FCIMPLEND + +/*====================================Round===================================== +** +==============================================================================*/ +FCIMPL1(float, COMSingle::Round, float x) + FCALL_CONTRACT; + + // If the number has no fractional part do nothing + // This shortcut is necessary to workaround precision loss in borderline cases on some platforms + if (x == (float)((INT32)x)) { + return x; + } + + // We had a number that was equally close to 2 integers. + // We need to return the even one. + + float tempVal = (x + 0.5f); + float flrTempVal = floorf(tempVal); + + if ((flrTempVal == tempVal) && (fmodf(tempVal, 2.0f) != 0)) { + flrTempVal -= 1.0f; + } + + return _copysignf(flrTempVal, x); +FCIMPLEND + +/*=====================================Sin====================================== +** +==============================================================================*/ +FCIMPL1(float, COMSingle::Sin, float x) + FCALL_CONTRACT; + + return (float)sinf(x); +FCIMPLEND + +/*=====================================Sinh===================================== +** +==============================================================================*/ +FCIMPL1(float, COMSingle::Sinh, float x) + FCALL_CONTRACT; + + return (float)sinhf(x); +FCIMPLEND + +/*=====================================Sqrt===================================== +** +==============================================================================*/ +FCIMPL1(float, COMSingle::Sqrt, float x) + FCALL_CONTRACT; + + return (float)sqrtf(x); +FCIMPLEND + +/*=====================================Tan====================================== +** +==============================================================================*/ +FCIMPL1(float, COMSingle::Tan, float x) + FCALL_CONTRACT; + + return (float)tanf(x); +FCIMPLEND + +/*=====================================Tanh===================================== +** +==============================================================================*/ +FCIMPL1(float, COMSingle::Tanh, float x) + FCALL_CONTRACT; + + return (float)tanhf(x); +FCIMPLEND + #ifdef _MSC_VER #pragma float_control(precise, on ) #endif diff --git a/src/classlibnative/inc/floatsingle.h b/src/classlibnative/inc/floatsingle.h index 6d123ec001..f8a1dda0fd 100644 --- a/src/classlibnative/inc/floatsingle.h +++ b/src/classlibnative/inc/floatsingle.h @@ -11,6 +11,25 @@ class COMSingle { public: FCDECL1(static float, Abs, float x); + FCDECL1(static float, Acos, float x); + FCDECL1(static float, Asin, float x); + FCDECL1(static float, Atan, float x); + FCDECL2(static float, Atan2, float y, float x); + FCDECL1(static float, Ceil, float x); + FCDECL1(static float, Cos, float x); + FCDECL1(static float, Cosh, float x); + FCDECL1(static float, Exp, float x); + FCDECL1(static float, Floor, float x); + FCDECL1(static float, Log, float x); + FCDECL1(static float, Log10, float x); + FCDECL1(static float, ModF, float* iptr); + FCDECL2(static float, Pow, float x, float y); + FCDECL1(static float, Round, float x); + FCDECL1(static float, Sin, float x); + FCDECL1(static float, Sinh, float x); + FCDECL1(static float, Sqrt, float x); + FCDECL1(static float, Tan, float x); + FCDECL1(static float, Tanh, float x); }; #endif // _FLOATSINGLE_H_ |