summaryrefslogtreecommitdiff
path: root/src/classlibnative
diff options
context:
space:
mode:
authorTanner Gooding <tannergooding@users.noreply.github.com>2016-10-18 02:56:53 -0700
committerJan Vorlicek <janvorli@microsoft.com>2016-10-18 11:56:53 +0200
commit6057b18d33216c3ee1436411e42e75a915a4714b (patch)
tree79f5282a27fbfb579763487a96c0e8f1bb56a9af /src/classlibnative
parentbed314bb3005e3c5fc0b3c0723e398e702e08f65 (diff)
downloadcoreclr-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.cpp217
-rw-r--r--src/classlibnative/inc/floatsingle.h19
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_