summaryrefslogtreecommitdiff
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
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.
-rw-r--r--src/classlibnative/float/floatsingle.cpp217
-rw-r--r--src/classlibnative/inc/floatsingle.h19
-rw-r--r--src/mscorlib/model.xml34
-rw-r--r--src/mscorlib/mscorlib.shared.sources.props1
-rw-r--r--src/mscorlib/ref/mscorlib.cs57
-rw-r--r--src/mscorlib/src/System/BitConverter.cs12
-rw-r--r--src/mscorlib/src/System/MathF.cs292
-rw-r--r--src/mscorlib/src/System/Single.cs8
-rw-r--r--src/pal/inc/pal.h27
-rw-r--r--src/pal/src/cruntime/math.cpp367
-rw-r--r--src/pal/src/include/pal/palinternal.h26
-rw-r--r--src/pal/tests/palsuite/c_runtime/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_finitef/CMakeLists.txt3
-rw-r--r--src/pal/tests/palsuite/c_runtime/_finitef/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_finitef/test1/test1.c119
-rw-r--r--src/pal/tests/palsuite/c_runtime/_finitef/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/_isnanf/CMakeLists.txt3
-rw-r--r--src/pal/tests/palsuite/c_runtime/_isnanf/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_isnanf/test1/test1.c115
-rw-r--r--src/pal/tests/palsuite/c_runtime/_isnanf/test1/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/c_runtime/acosf/CMakeLists.txt3
-rw-r--r--src/pal/tests/palsuite/c_runtime/acosf/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/acosf/test1/test1.c129
-rw-r--r--src/pal/tests/palsuite/c_runtime/acosf/test1/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/asinf/CMakeLists.txt3
-rw-r--r--src/pal/tests/palsuite/c_runtime/asinf/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/asinf/test1/test1.c145
-rw-r--r--src/pal/tests/palsuite/c_runtime/asinf/test1/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/atan2f/CMakeLists.txt3
-rw-r--r--src/pal/tests/palsuite/c_runtime/atan2f/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/atan2f/test1/test1.c147
-rw-r--r--src/pal/tests/palsuite/c_runtime/atan2f/test1/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/atanf/CMakeLists.txt3
-rw-r--r--src/pal/tests/palsuite/c_runtime/atanf/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/atanf/test1/test1.c127
-rw-r--r--src/pal/tests/palsuite/c_runtime/atanf/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/ceilf/CMakeLists.txt3
-rw-r--r--src/pal/tests/palsuite/c_runtime/ceilf/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/ceilf/test1/test1.c131
-rw-r--r--src/pal/tests/palsuite/c_runtime/ceilf/test1/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/cosf/CMakeLists.txt3
-rw-r--r--src/pal/tests/palsuite/c_runtime/cosf/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/cosf/test1/test1.c130
-rw-r--r--src/pal/tests/palsuite/c_runtime/cosf/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/coshf/CMakeLists.txt3
-rw-r--r--src/pal/tests/palsuite/c_runtime/coshf/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/coshf/test1/test1.c129
-rw-r--r--src/pal/tests/palsuite/c_runtime/coshf/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/expf/CMakeLists.txt3
-rw-r--r--src/pal/tests/palsuite/c_runtime/expf/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/expf/test1/test1.c137
-rw-r--r--src/pal/tests/palsuite/c_runtime/expf/test1/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/floorf/CMakeLists.txt3
-rw-r--r--src/pal/tests/palsuite/c_runtime/floorf/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/floorf/test1/test1.c131
-rw-r--r--src/pal/tests/palsuite/c_runtime/floorf/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/log10f/CMakeLists.txt3
-rw-r--r--src/pal/tests/palsuite/c_runtime/log10f/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/log10f/test1/test1.c144
-rw-r--r--src/pal/tests/palsuite/c_runtime/log10f/test1/testinfo.dat17
-rw-r--r--src/pal/tests/palsuite/c_runtime/logf/CMakeLists.txt3
-rw-r--r--src/pal/tests/palsuite/c_runtime/logf/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/logf/test1/test1.c139
-rw-r--r--src/pal/tests/palsuite/c_runtime/logf/test1/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/powf/CMakeLists.txt3
-rw-r--r--src/pal/tests/palsuite/c_runtime/powf/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/powf/test1/test1.c229
-rw-r--r--src/pal/tests/palsuite/c_runtime/powf/test1/testinfo.dat17
-rw-r--r--src/pal/tests/palsuite/c_runtime/sinf/CMakeLists.txt3
-rw-r--r--src/pal/tests/palsuite/c_runtime/sinf/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/sinf/test1/test1.c130
-rw-r--r--src/pal/tests/palsuite/c_runtime/sinf/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/sinhf/CMakeLists.txt3
-rw-r--r--src/pal/tests/palsuite/c_runtime/sinhf/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/sinhf/test1/test1.c129
-rw-r--r--src/pal/tests/palsuite/c_runtime/sinhf/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/sqrtf/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/sqrtf/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/sqrtf/test1/test1.c122
-rw-r--r--src/pal/tests/palsuite/c_runtime/sqrtf/test1/testinfo.dat17
-rw-r--r--src/pal/tests/palsuite/c_runtime/tanf/CMakeLists.txt3
-rw-r--r--src/pal/tests/palsuite/c_runtime/tanf/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/tanf/test1/test1.c136
-rw-r--r--src/pal/tests/palsuite/c_runtime/tanf/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/tanhf/CMakeLists.txt3
-rw-r--r--src/pal/tests/palsuite/c_runtime/tanhf/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/tanhf/test1/test1.c129
-rw-r--r--src/pal/tests/palsuite/c_runtime/tanhf/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/paltestlist.txt19
-rw-r--r--src/pal/tests/palsuite/palverify.dat19
-rw-r--r--src/vm/ecalllist.h24
91 files changed, 4423 insertions, 1 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_
diff --git a/src/mscorlib/model.xml b/src/mscorlib/model.xml
index 0f18f46a7b..70b25972e3 100644
--- a/src/mscorlib/model.xml
+++ b/src/mscorlib/model.xml
@@ -447,6 +447,7 @@
</Type>
<Type Name="System.BitConverter">
<Member Name="DoubleToInt64Bits(System.Double)" />
+ <Member Name="Int32BitsToSingle(System.Int32)" />
<Member Name="Int64BitsToDouble(System.Int64)" />
<Member MemberType="Field" Name="IsLittleEndian" />
<Member Name="GetBytes(System.Boolean)" />
@@ -459,6 +460,7 @@
<Member Name="GetBytes(System.UInt32)" />
<Member Name="GetBytes(System.UInt64)" />
<Member Name="GetBytes(System.UInt16)" />
+ <Member Name="SingleToInt32Bits(System.Single)" />
<Member Name="ToBoolean(System.Byte[],System.Int32)" />
<Member Name="ToChar(System.Byte[],System.Int32)" />
<Member Name="ToDouble(System.Byte[],System.Int32)" />
@@ -3660,6 +3662,38 @@
<Member Name="Truncate(System.Decimal)" />
<Member Name="Truncate(System.Double)" />
</Type>
+ <Type Name="System.MathF">
+ <Member MemberType="Field" Name="E" />
+ <Member MemberType="Field" Name="PI" />
+ <Member Name="Abs(System.Single)" />
+ <Member Name="Acos(System.Single)" />
+ <Member Name="Asin(System.Single)" />
+ <Member Name="Atan(System.Single)" />
+ <Member Name="Atan2(System.Single,System.Single)" />
+ <Member Name="Ceiling(System.Single)"/>
+ <Member Name="Cos(System.Single)" />
+ <Member Name="Cosh(System.Single)" />
+ <Member Name="Exp(System.Single)" />
+ <Member Name="Floor(System.Single)" />
+ <Member Name="IEEERemainder(System.Single,System.Single)" />
+ <Member Name="Log(System.Single)" />
+ <Member Name="Log(System.Single,System.Single)" />
+ <Member Name="Log10(System.Single)" />
+ <Member Name="Max(System.Single,System.Single)" />
+ <Member Name="Min(System.Single,System.Single)" />
+ <Member Name="Pow(System.Single,System.Single)" />
+ <Member Name="Round(System.Single)" />
+ <Member Name="Round(System.Single,System.Int32)" />
+ <Member Name="Round(System.Single,System.Int32,System.MidpointRounding)" />
+ <Member Name="Round(System.Single,System.MidpointRounding)" />
+ <Member Name="Sign(System.Single)" />
+ <Member Name="Sin(System.Single)" />
+ <Member Name="Sinh(System.Single)" />
+ <Member Name="Sqrt(System.Single)" />
+ <Member Name="Tan(System.Single)" />
+ <Member Name="Tanh(System.Single)" />
+ <Member Name="Truncate(System.Single)" />
+ </Type>
<Type Name="System.MemberAccessException">
<Member Name="#ctor" />
<Member Name="#ctor(System.String)" />
diff --git a/src/mscorlib/mscorlib.shared.sources.props b/src/mscorlib/mscorlib.shared.sources.props
index 459c18bc92..63c4e3f201 100644
--- a/src/mscorlib/mscorlib.shared.sources.props
+++ b/src/mscorlib/mscorlib.shared.sources.props
@@ -369,6 +369,7 @@
<SystemSources Include="$(BclSourcesRoot)\System\_LocalDataStoreMgr.cs" />
<SystemSources Include="$(BclSourcesRoot)\System\MarshalByRefObject.cs" />
<SystemSources Include="$(BclSourcesRoot)\System\Math.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\MathF.cs" />
<SystemSources Include="$(BclSourcesRoot)\System\mda.cs" />
<SystemSources Include="$(BclSourcesRoot)\System\MethodAccessException.cs" />
<SystemSources Include="$(BclSourcesRoot)\System\MidpointRounding.cs" />
diff --git a/src/mscorlib/ref/mscorlib.cs b/src/mscorlib/ref/mscorlib.cs
index 1e59ef794e..4160762186 100644
--- a/src/mscorlib/ref/mscorlib.cs
+++ b/src/mscorlib/ref/mscorlib.cs
@@ -603,7 +603,11 @@ namespace System
[System.CLSCompliantAttribute(false)]
public static byte[] GetBytes(ulong value) { throw null; }
[System.Security.SecuritySafeCriticalAttribute]
+ public static float Int32BitsToSingle(int value) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
public static double Int64BitsToDouble(long value) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static int SingleToInt32Bits(float value) { throw null; }
public static bool ToBoolean(byte[] value, int startIndex) { throw null; }
public static char ToChar(byte[] value, int startIndex) { throw null; }
[System.Security.SecuritySafeCriticalAttribute]
@@ -2622,6 +2626,59 @@ namespace System
public static decimal Truncate(decimal d) { throw null; }
public static double Truncate(double d) { throw null; }
}
+ public static partial class MathF
+ {
+ public const float E = 2.71828183f;
+ public const float PI = 3.14159265f;
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ public static float Abs(float x) { return default(float); }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ public static float Acos(float x) { return default(float); }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ public static float Asin(float x) { return default(float); }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ public static float Atan(float x) { return default(float); }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ public static float Atan2(float y, float x) { return default(float); }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ public static float Ceiling(float x) { return default(float); }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ public static float Cos(float x) { return default(float); }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ public static float Cosh(float x) { return default(float); }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ public static float Exp(float x) { return default(float); }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ public static float Floor(float x) { return default(float); }
+ public static float IEEERemainder(float x, float y) { return default(float); }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ public static float Log(float x) { return default(float); }
+ public static float Log(float x, float y) { return default(float); }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ public static float Log10(float x) { return default(float); }
+ public static float Max(float x, float y) { return default(float); }
+ public static float Min(float x, float y) { return default(float); }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ public static float Pow(float x, float y) { return default(float); }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ public static float Round(float x) { return default(float); }
+ public static float Round(float x, int digits) { return default(float); }
+ public static float Round(float x, int digits, System.MidpointRounding mode) { return default(float); }
+ public static float Round(float x, System.MidpointRounding mode) { return default(float); }
+ public static int Sign(float x) { return default(int); }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ public static float Sin(float x) { return default(float); }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ public static float Sinh(float x) { return default(float); }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static float Sqrt(float x) { return default(float); }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ public static float Tan(float x) { return default(float); }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ public static float Tanh(float x) { return default(float); }
+ public static float Truncate(float x) { return default(float); }
+ }
[System.Runtime.InteropServices.ComVisibleAttribute(true)]
public partial class MemberAccessException : System.SystemException
{
diff --git a/src/mscorlib/src/System/BitConverter.cs b/src/mscorlib/src/System/BitConverter.cs
index 5ecb1302d6..8be545c67e 100644
--- a/src/mscorlib/src/System/BitConverter.cs
+++ b/src/mscorlib/src/System/BitConverter.cs
@@ -446,6 +446,16 @@ namespace System {
[SecuritySafeCritical]
public static unsafe double Int64BitsToDouble(long value) {
return *((double*)&value);
- }
+ }
+
+ [SecuritySafeCritical]
+ public static unsafe int SingleToInt32Bits(float value) {
+ return *((int*)&value);
+ }
+
+ [SecuritySafeCritical]
+ public static unsafe float Int32BitsToSingle(int value) {
+ return *((float*)&value);
+ }
}
}
diff --git a/src/mscorlib/src/System/MathF.cs b/src/mscorlib/src/System/MathF.cs
new file mode 100644
index 0000000000..bca5559b80
--- /dev/null
+++ b/src/mscorlib/src/System/MathF.cs
@@ -0,0 +1,292 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Purpose: Some single-precision floating-point math operations
+**
+===========================================================*/
+namespace System {
+
+ //This class contains only static members and doesn't require serialization.
+ using System;
+ using System.Runtime;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.ConstrainedExecution;
+ using System.Runtime.Versioning;
+ using System.Diagnostics.Contracts;
+
+ public static class MathF
+ {
+ private static float singleRoundLimit = 1e8f;
+
+ private const int maxRoundingDigits = 6;
+
+ // This table is required for the Round function which can specify the number of digits to round to
+ private static float[] roundPower10Single = new float[] {
+ 1e0f, 1e1f, 1e2f, 1e3f, 1e4f, 1e5f, 1e6f
+ };
+
+ public const float PI = 3.14159265f;
+
+ public const float E = 2.71828183f;
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern float Abs(float x);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern float Acos(float x);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern float Asin(float x);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern float Atan(float x);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern float Atan2(float y, float x);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern float Ceiling(float x);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern float Cos(float x);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern float Cosh(float x);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern float Exp(float x);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern float Floor(float x);
+
+ public static float IEEERemainder(float x, float y)
+ {
+ if (float.IsNaN(x))
+ {
+ return x; // IEEE 754-2008: NaN payload must be preserved
+ }
+
+ if (float.IsNaN(y))
+ {
+ return y; // IEEE 754-2008: NaN payload must be preserved
+ }
+
+ var regularMod = x % y;
+
+ if (float.IsNaN(regularMod))
+ {
+ return float.NaN;
+ }
+
+ if ((regularMod == 0) && float.IsNegative(x))
+ {
+ return float.NegativeZero;
+ }
+
+ var alternativeResult = (regularMod - (Abs(y) * Sign(x)));
+
+ if (Abs(alternativeResult) == Abs(regularMod))
+ {
+ var divisionResult = x / y;
+ var roundedResult = Round(divisionResult);
+
+ if (Abs(roundedResult) > Abs(divisionResult))
+ {
+ return alternativeResult;
+ }
+ else
+ {
+ return regularMod;
+ }
+ }
+
+ if (Math.Abs(alternativeResult) < Math.Abs(regularMod))
+ {
+ return alternativeResult;
+ }
+ else
+ {
+ return regularMod;
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern float Log(float x);
+
+ public static float Log(float x, float y)
+ {
+ if (float.IsNaN(x))
+ {
+ return x; // IEEE 754-2008: NaN payload must be preserved
+ }
+
+ if (float.IsNaN(y))
+ {
+ return y; // IEEE 754-2008: NaN payload must be preserved
+ }
+
+ if (y == 1)
+ {
+ return float.NaN;
+ }
+
+ if ((x != 1) && ((y == 0) || float.IsPositiveInfinity(y)))
+ {
+ return float.NaN;
+ }
+
+ return Log(x) / Log(y);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern float Log10(float x);
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ public static float Max(float x, float y) => ((x > y) || float.IsNaN(x)) ? x : y;
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ public static float Min(float x, float y) => ((x < y) || float.IsNaN(x)) ? x : y;
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern float Pow(float x, float y);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern float Round(float x);
+
+ public static float Round(float x, int digits)
+ {
+ if ((digits < 0) || (digits > maxRoundingDigits))
+ {
+ throw new ArgumentOutOfRangeException(nameof(digits), Environment.GetResourceString("ArgumentOutOfRange_RoundingDigits"));
+ }
+ Contract.EndContractBlock();
+
+ return InternalRound(x, digits, MidpointRounding.ToEven);
+ }
+
+ public static float Round(float x, int digits, MidpointRounding mode)
+ {
+ if ((digits < 0) || (digits > maxRoundingDigits))
+ {
+ throw new ArgumentOutOfRangeException(nameof(digits), Environment.GetResourceString("ArgumentOutOfRange_RoundingDigits"));
+ }
+
+ if (mode < MidpointRounding.ToEven || mode > MidpointRounding.AwayFromZero)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidEnumx", mode, nameof(MidpointRounding)), nameof(mode));
+ }
+ Contract.EndContractBlock();
+
+ return InternalRound(x, digits, mode);
+ }
+
+ public static float Round(float x, MidpointRounding mode)
+ {
+ if (mode < MidpointRounding.ToEven || mode > MidpointRounding.AwayFromZero)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidEnumx", mode, nameof(MidpointRounding)), nameof(mode));
+ }
+ Contract.EndContractBlock();
+
+ return InternalRound(x, 0, mode);
+ }
+
+ public static int Sign(float x)
+ {
+ if (x < 0)
+ {
+ return -1;
+ }
+ else if (x > 0)
+ {
+ return 1;
+ }
+ else if (x == 0)
+ {
+ return 0;
+ }
+
+ throw new ArithmeticException(Environment.GetResourceString("Arithmetic_NaN"));
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern float Sin(float x);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern float Sinh(float x);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern float Sqrt(float x);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern float Tan(float x);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern float Tanh(float x);
+
+ public static float Truncate(float x) => InternalTruncate(x);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private static unsafe float InternalRound(float x, int digits, MidpointRounding mode)
+ {
+ if (Abs(x) < singleRoundLimit)
+ {
+ var power10 = roundPower10Single[digits];
+
+ x *= power10;
+
+ if (mode == MidpointRounding.AwayFromZero)
+ {
+ var fraction = SplitFractionSingle(&x);
+
+ if (Abs(fraction) >= 0.5f)
+ {
+ x += Sign(fraction);
+ }
+ }
+ else
+ {
+ x = Round(x);
+ }
+
+ x /= power10;
+ }
+
+ return x;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private unsafe static float InternalTruncate(float x)
+ {
+ SplitFractionSingle(&x);
+ return x;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static unsafe extern float SplitFractionSingle(float* x);
+ }
+}
diff --git a/src/mscorlib/src/System/Single.cs b/src/mscorlib/src/System/Single.cs
index 6a77f086b5..a2d3b13f3f 100644
--- a/src/mscorlib/src/System/Single.cs
+++ b/src/mscorlib/src/System/Single.cs
@@ -37,6 +37,8 @@ namespace System {
public const float NegativeInfinity = (float)-1.0 / (float)0.0;
public const float NaN = (float)0.0 / (float)0.0;
+ internal static float NegativeZero = BitConverter.Int32BitsToSingle(unchecked((int)0x80000000));
+
[Pure]
[System.Security.SecuritySafeCritical] // auto-generated
[System.Runtime.Versioning.NonVersionable]
@@ -65,6 +67,12 @@ namespace System {
public unsafe static bool IsNaN(float f) {
return (*(int*)(&f) & 0x7FFFFFFF) > 0x7F800000;
}
+
+ [Pure]
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal unsafe static bool IsNegative(float f) {
+ return (*(uint*)(&f) & 0x80000000) == 0x80000000;
+ }
// Compares this object to another object, returning an integer that
// indicates the relationship.
diff --git a/src/pal/inc/pal.h b/src/pal/inc/pal.h
index 792e24e07c..e698a26e04 100644
--- a/src/pal/inc/pal.h
+++ b/src/pal/inc/pal.h
@@ -5791,6 +5791,13 @@ CoCreateGuid(OUT GUID * pguid);
#define log PAL_log
#define log10 PAL_log10
#define pow PAL_pow
+#define acosf PAL_acosf
+#define asinf PAL_asinf
+#define atan2f PAL_atan2f
+#define expf PAL_expf
+#define logf PAL_logf
+#define log10f PAL_log10f
+#define powf PAL_powf
#define malloc PAL_malloc
#define free PAL_free
#define mkstemp PAL_mkstemp
@@ -6040,9 +6047,29 @@ PALIMPORT double __cdecl sqrt(double);
PALIMPORT double __cdecl tan(double);
PALIMPORT double __cdecl tanh(double);
+PALIMPORT int __cdecl _finitef(float);
+PALIMPORT int __cdecl _isnanf(float);
+PALIMPORT float __cdecl _copysignf(float, float);
+PALIMPORT float __cdecl acosf(float);
+PALIMPORT float __cdecl asinf(float);
+PALIMPORT float __cdecl atanf(float);
+PALIMPORT float __cdecl atan2f(float, float);
+PALIMPORT float __cdecl ceilf(float);
+PALIMPORT float __cdecl cosf(float);
+PALIMPORT float __cdecl coshf(float);
+PALIMPORT float __cdecl expf(float);
PALIMPORT float __cdecl fabsf(float);
+PALIMPORT float __cdecl floorf(float);
PALIMPORT float __cdecl fmodf(float, float);
+PALIMPORT float __cdecl logf(float);
+PALIMPORT float __cdecl log10f(float);
PALIMPORT float __cdecl modff(float, float*);
+PALIMPORT float __cdecl powf(float, float);
+PALIMPORT float __cdecl sinf(float);
+PALIMPORT float __cdecl sinhf(float);
+PALIMPORT float __cdecl sqrtf(float);
+PALIMPORT float __cdecl tanf(float);
+PALIMPORT float __cdecl tanhf(float);
#ifndef PAL_STDCPP_COMPAT
diff --git a/src/pal/src/cruntime/math.cpp b/src/pal/src/cruntime/math.cpp
index 7075fd60f9..08f4192998 100644
--- a/src/pal/src/cruntime/math.cpp
+++ b/src/pal/src/cruntime/math.cpp
@@ -35,6 +35,12 @@ Abstract:
#define IS_DBL_NEGZERO(x) (((*((INT64*)((void*)&x))) & I64(0xFFFFFFFFFFFFFFFF)) == I64(0x8000000000000000))
+#define PAL_NAN_FLT sqrtf(-1.0f)
+#define PAL_POSINF_FLT -logf(0.0f)
+#define PAL_NEGINF_FLT logf(0.0f)
+
+#define IS_FLT_NEGZERO(x) (((*((INT32*)((void*)&x))) & 0xFFFFFFFF) == 0x80000000)
+
SET_DEFAULT_DEBUG_CHANNEL(CRT);
/*++
@@ -422,3 +428,364 @@ PALIMPORT double __cdecl PAL_pow(double x, double y)
PERF_EXIT(pow);
return ret;
}
+
+/*++
+Function:
+ _finitef
+
+Determines whether given single-precision floating point value is finite.
+
+Return Value
+
+_finitef returns a nonzero value (TRUE) if its argument x is not
+infinite, that is, if -INF < x < +INF. It returns 0 (FALSE) if the
+argument is infinite or a NaN.
+
+Parameter
+
+x Single-precision floating-point value
+
+--*/
+int __cdecl _finitef(float x)
+{
+ int ret;
+ PERF_ENTRY(_finitef);
+ ENTRY("_finitef (x=%f)\n", x);
+
+#if defined(_IA64_) && defined (_HPUX_)
+ ret = !isnan(x) && (x != PAL_POSINF_FLT) && (x != PAL_NEGINF_FLT);
+#else
+ ret = isfinite(x);
+#endif
+
+ LOGEXIT("_finitef returns int %d\n", ret);
+ PERF_EXIT(_finitef);
+ return ret;
+}
+
+/*++
+Function:
+ _isnanf
+
+See MSDN doc
+--*/
+int __cdecl _isnanf(float x)
+{
+ int ret;
+ PERF_ENTRY(_isnanf);
+ ENTRY("_isnanf (x=%f)\n", x);
+
+ ret = isnan(x);
+
+ LOGEXIT("_isnanf returns int %d\n", ret);
+ PERF_EXIT(_isnanf);
+ return ret;
+}
+
+/*++
+Function:
+ _copysignf
+
+See MSDN doc
+--*/
+float __cdecl _copysignf(float x, float y)
+{
+ float ret;
+ PERF_ENTRY(_copysignf);
+ ENTRY("_copysignf (x=%f, y=%f)\n", x, y);
+
+ ret = copysign(x, y);
+
+ LOGEXIT("_copysignf returns float %f\n", ret);
+ PERF_EXIT(_copysignf);
+ return ret;
+}
+
+/*++
+Function:
+ acosf
+
+See MSDN.
+--*/
+PALIMPORT float __cdecl PAL_acosf(float x)
+{
+ float ret;
+ PERF_ENTRY(acosf);
+ ENTRY("acosf (x=%f)\n", x);
+
+#if !HAVE_COMPATIBLE_ACOS
+ errno = 0;
+#endif // HAVE_COMPATIBLE_ACOS
+
+ ret = acosf(x);
+
+#if !HAVE_COMPATIBLE_ACOS
+ if (errno == EDOM)
+ {
+ ret = PAL_NAN_FLT; // NaN
+ }
+#endif // HAVE_COMPATIBLE_ACOS
+
+ LOGEXIT("acosf returns float %f\n", ret);
+ PERF_EXIT(acosf);
+ return ret;
+}
+
+/*++
+Function:
+ asinf
+
+See MSDN.
+--*/
+PALIMPORT float __cdecl PAL_asinf(float x)
+{
+ float ret;
+ PERF_ENTRY(asinf);
+ ENTRY("asinf (x=%f)\n", x);
+
+#if !HAVE_COMPATIBLE_ASIN
+ errno = 0;
+#endif // HAVE_COMPATIBLE_ASIN
+
+ ret = asinf(x);
+
+#if !HAVE_COMPATIBLE_ASIN
+ if (errno == EDOM)
+ {
+ ret = PAL_NAN_FLT; // NaN
+ }
+#endif // HAVE_COMPATIBLE_ASIN
+
+ LOGEXIT("asinf returns float %f\n", ret);
+ PERF_EXIT(asinf);
+ return ret;
+}
+
+/*++
+Function:
+ atan2f
+
+See MSDN.
+--*/
+PALIMPORT float __cdecl PAL_atan2f(float y, float x)
+{
+ float ret;
+ PERF_ENTRY(atan2f);
+ ENTRY("atan2f (y=%f, x=%f)\n", y, x);
+
+#if !HAVE_COMPATIBLE_ATAN2
+ errno = 0;
+#endif // !HAVE_COMPATIBLE_ATAN2
+
+ ret = atan2f(y, x);
+
+#if !HAVE_COMPATIBLE_ATAN2
+ if ((errno == EDOM) && (x == 0.0f) && (y == 0.0f))
+ {
+ const float sign_x = copysign(1.0f, x);
+ const float sign_y = copysign(1.0f, y);
+
+ if (sign_x > 0)
+ {
+ ret = copysign(0.0f, sign_y);
+ }
+ else
+ {
+ ret = copysign(atan2f(0.0f, -1.0f), sign_y);
+ }
+ }
+#endif // !HAVE_COMPATIBLE_ATAN2
+
+ LOGEXIT("atan2f returns float %f\n", ret);
+ PERF_EXIT(atan2f);
+ return ret;
+}
+
+/*++
+Function:
+ expf
+
+See MSDN.
+--*/
+PALIMPORT float __cdecl PAL_expf(float x)
+{
+ float ret;
+ PERF_ENTRY(expf);
+ ENTRY("expf (x=%f)\n", x);
+
+#if !HAVE_COMPATIBLE_EXP
+ if (x == 1.0f)
+ {
+ ret = M_E;
+ }
+ else
+ {
+#endif // HAVE_COMPATIBLE_EXP
+
+ ret = expf(x);
+
+#if !HAVE_COMPATIBLE_EXP
+ }
+#endif // HAVE_COMPATIBLE_EXP
+
+ LOGEXIT("expf returns float %f\n", ret);
+ PERF_EXIT(expf);
+ return ret;
+}
+
+/*++
+Function:
+ logf
+
+See MSDN.
+--*/
+PALIMPORT float __cdecl PAL_logf(float x)
+{
+ float ret;
+ PERF_ENTRY(logf);
+ ENTRY("logf (x=%f)\n", x);
+
+#if !HAVE_COMPATIBLE_LOG
+ errno = 0;
+#endif // !HAVE_COMPATIBLE_LOG
+
+ ret = logf(x);
+
+#if !HAVE_COMPATIBLE_LOG
+ if ((errno == EDOM) && (x < 0))
+ {
+ ret = PAL_NAN_FLT; // NaN
+ }
+#endif // !HAVE_COMPATIBLE_LOG
+
+ LOGEXIT("logf returns float %f\n", ret);
+ PERF_EXIT(logf);
+ return ret;
+}
+
+/*++
+Function:
+ log10f
+
+See MSDN.
+--*/
+PALIMPORT float __cdecl PAL_log10f(float x)
+{
+ float ret;
+ PERF_ENTRY(log10f);
+ ENTRY("log10f (x=%f)\n", x);
+
+#if !HAVE_COMPATIBLE_LOG10
+ errno = 0;
+#endif // !HAVE_COMPATIBLE_LOG10
+
+ ret = log10f(x);
+
+#if !HAVE_COMPATIBLE_LOG10
+ if ((errno == EDOM) && (x < 0))
+ {
+ ret = PAL_NAN_FLT; // NaN
+ }
+#endif // !HAVE_COMPATIBLE_LOG10
+
+ LOGEXIT("log10f returns float %f\n", ret);
+ PERF_EXIT(log10f);
+ return ret;
+}
+
+/*++
+Function:
+ powf
+
+See MSDN.
+--*/
+PALIMPORT float __cdecl PAL_powf(float x, float y)
+{
+ float ret;
+ PERF_ENTRY(powf);
+ ENTRY("powf (x=%f, y=%f)\n", x, y);
+
+#if !HAVE_COMPATIBLE_POW
+ if ((y == PAL_POSINF_FLT) && !isnan(x)) // +Inf
+ {
+ if (x == 1.0f)
+ {
+ ret = x;
+ }
+ else if (x == -1.0f)
+ {
+ ret = PAL_NAN_FLT; // NaN
+ }
+ else if ((x > -1.0f) && (x < 1.0f))
+ {
+ ret = 0.0f;
+ }
+ else
+ {
+ ret = PAL_POSINF_FLT; // +Inf
+ }
+ }
+ else if ((y == PAL_NEGINF_FLT) && !isnan(x)) // -Inf
+ {
+ if (x == 1.0f)
+ {
+ ret = x;
+ }
+ else if (x == -1.0f)
+ {
+ ret = PAL_NAN_FLT; // NaN
+ }
+ else if ((x > -1.0f) && (x < 1.0f))
+ {
+ ret = PAL_POSINF_FLT; // +Inf
+ }
+ else
+ {
+ ret = 0.0f;
+ }
+ }
+ else if (IS_FLT_NEGZERO(x) && (y == -1.0f))
+ {
+ ret = PAL_NEGINF_FLT; // -Inf
+ }
+ else if ((x == 0.0f) && (y < 0.0f))
+ {
+ ret = PAL_POSINF_FLT; // +Inf
+ }
+ else
+#endif // !HAVE_COMPATIBLE_POW
+
+ if ((y == 0.0f) && isnan(x))
+ {
+ // Windows returns NaN for powf(NaN, 0), but POSIX specifies
+ // a return value of 1 for that case. We need to return
+ // the same result as Windows.
+ ret = PAL_NAN_FLT;
+ }
+ else
+ {
+ ret = powf(x, y);
+ }
+
+#if !HAVE_VALID_NEGATIVE_INF_POW
+ if ((ret == PAL_POSINF_FLT) && (x < 0) && isfinite(x) && (ceilf(y / 2) != floorf(y / 2)))
+ {
+ ret = PAL_NEGINF_FLT; // -Inf
+ }
+#endif // !HAVE_VALID_NEGATIVE_INF_POW
+
+#if !HAVE_VALID_POSITIVE_INF_POW
+ /*
+ * The (ceil(y/2) == floor(y/2)) test is slower, but more robust for platforms where large y
+ * will return the wrong result for ((long) y % 2 == 0). See PAL_pow(double) above for more details.
+ */
+ if ((ret == PAL_NEGINF_FLT) && (x < 0) && isfinite(x) && (ceilf(y / 2) == floorf(y / 2)))
+ {
+ ret = PAL_POSINF_FLT; // +Inf
+ }
+#endif // !HAVE_VALID_POSITIVE_INF_POW
+
+ LOGEXIT("powf returns float %f\n", ret);
+ PERF_EXIT(powf);
+ return ret;
+}
diff --git a/src/pal/src/include/pal/palinternal.h b/src/pal/src/include/pal/palinternal.h
index 88d47bb348..fa51eccb94 100644
--- a/src/pal/src/include/pal/palinternal.h
+++ b/src/pal/src/include/pal/palinternal.h
@@ -216,9 +216,18 @@ function_name() to call the system's implementation
#define sqrt DUMMY_sqrt
#define tan DUMMY_tan
#define tanh DUMMY_tanh
+#define ceilf DUMMY_ceilf
+#define cosf DUMMY_cosf
+#define coshf DUMMY_coshf
#define fabsf DUMMY_fabsf
+#define floorf DUMMY_floorf
#define fmodf DUMMY_fmodf
#define modff DUMMY_modff
+#define sinf DUMMY_sinf
+#define sinhf DUMMY_sinhf
+#define sqrtf DUMMY_sqrtf
+#define tanf DUMMY_tanf
+#define tanhf DUMMY_tanhf
/* RAND_MAX needed to be renamed to avoid duplicate definition when including
stdlib.h header files. PAL_RAND_MAX should have the same value as RAND_MAX
@@ -457,9 +466,26 @@ function_name() to call the system's implementation
#undef sqrt
#undef tan
#undef tanh
+#undef acosf
+#undef asinf
+#undef atanf
+#undef atan2f
+#undef ceilf
+#undef cosf
+#undef coshf
+#undef expf
#undef fabsf
+#undef floorf
#undef fmodf
+#undef logf
+#undef log10f
#undef modff
+#undef powf
+#undef sinf
+#undef sinhf
+#undef sqrtf
+#undef tanf
+#undef tanhf
#undef rand
#undef srand
#undef errno
diff --git a/src/pal/tests/palsuite/c_runtime/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/CMakeLists.txt
index 533454c285..a3a1eb4e73 100644
--- a/src/pal/tests/palsuite/c_runtime/CMakeLists.txt
+++ b/src/pal/tests/palsuite/c_runtime/CMakeLists.txt
@@ -2,16 +2,23 @@ cmake_minimum_required(VERSION 2.8.12.2)
add_subdirectory(abs)
add_subdirectory(acos)
+add_subdirectory(acosf)
add_subdirectory(asin)
+add_subdirectory(asinf)
add_subdirectory(atan)
add_subdirectory(atan2)
+add_subdirectory(atan2f)
+add_subdirectory(atanf)
add_subdirectory(atof)
add_subdirectory(atoi)
add_subdirectory(atol)
add_subdirectory(bsearch)
add_subdirectory(ceil)
+add_subdirectory(ceilf)
add_subdirectory(cos)
+add_subdirectory(cosf)
add_subdirectory(cosh)
+add_subdirectory(coshf)
# TODO: make this test compile
# add_subdirectory(ctime)
@@ -19,6 +26,7 @@ add_subdirectory(cosh)
add_subdirectory(errno)
add_subdirectory(exit)
add_subdirectory(exp)
+add_subdirectory(expf)
add_subdirectory(fabs)
add_subdirectory(fabsf)
add_subdirectory(fclose)
@@ -27,6 +35,7 @@ add_subdirectory(ferror)
add_subdirectory(fflush)
add_subdirectory(fgets)
add_subdirectory(floor)
+add_subdirectory(floorf)
add_subdirectory(fmod)
add_subdirectory(fmodf)
add_subdirectory(fopen)
@@ -57,6 +66,8 @@ add_subdirectory(llabs)
add_subdirectory(localtime)
add_subdirectory(log)
add_subdirectory(log10)
+add_subdirectory(log10f)
+add_subdirectory(logf)
add_subdirectory(malloc)
add_subdirectory(memchr)
add_subdirectory(memcmp)
@@ -66,14 +77,18 @@ add_subdirectory(memset)
add_subdirectory(modf)
add_subdirectory(modff)
add_subdirectory(pow)
+add_subdirectory(powf)
add_subdirectory(printf)
add_subdirectory(qsort)
add_subdirectory(rand_srand)
add_subdirectory(realloc)
add_subdirectory(sin)
+add_subdirectory(sinf)
add_subdirectory(sinh)
+add_subdirectory(sinhf)
add_subdirectory(sprintf)
add_subdirectory(sqrt)
+add_subdirectory(sqrtf)
add_subdirectory(sscanf)
add_subdirectory(strcat)
add_subdirectory(strchr)
@@ -94,7 +109,9 @@ add_subdirectory(strtoul)
add_subdirectory(swprintf)
add_subdirectory(swscanf)
add_subdirectory(tan)
+add_subdirectory(tanf)
add_subdirectory(tanh)
+add_subdirectory(tanhf)
add_subdirectory(time)
add_subdirectory(tolower)
add_subdirectory(toupper)
@@ -125,6 +142,7 @@ add_subdirectory(_alloca)
add_subdirectory(_ecvt)
add_subdirectory(_fdopen)
add_subdirectory(_finite)
+add_subdirectory(_finitef)
add_subdirectory(_fullpath)
# TODO: make this test compile
@@ -132,6 +150,7 @@ add_subdirectory(_fullpath)
add_subdirectory(_getw)
add_subdirectory(_isnan)
+add_subdirectory(_isnanf)
add_subdirectory(_itow)
add_subdirectory(_makepath)
add_subdirectory(_mbsdec)
diff --git a/src/pal/tests/palsuite/c_runtime/_finitef/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_finitef/CMakeLists.txt
new file mode 100644
index 0000000000..5e1ef7f28b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_finitef/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
diff --git a/src/pal/tests/palsuite/c_runtime/_finitef/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_finitef/test1/CMakeLists.txt
new file mode 100644
index 0000000000..9ef630fbb2
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_finitef/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_finitef_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_finitef_test1 coreclrpal)
+
+target_link_libraries(paltest_finitef_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_finitef/test1/test1.c b/src/pal/tests/palsuite/c_runtime/_finitef/test1/test1.c
new file mode 100644
index 0000000000..f9a1109a66
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_finitef/test1/test1.c
@@ -0,0 +1,119 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Checks that _finitef correctly classifies all types
+** of floating point numbers (NaN, -Infinity, Infinity,
+** finite nonzero, unnormalized, 0, and -0)
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+/*
+The IEEE single precision floating point standard looks like this:
+
+ S EEEEEEEE FFFFFFFFFFFFFFFFFFFFFFF
+ 0 1 8 9 31
+
+S is the sign bit. The E bits are the exponent, and the 23 F bits are
+the fraction. These represent a value, V.
+
+If E=255 and F is nonzero, then V=NaN ("Not a number")
+If E=255 and F is zero and S is 1, then V=-Infinity
+If E=255 and F is zero and S is 0, then V=Infinity
+If 0<E<255 then V=(-1)^S * 2^(E-1028) * (1.F) where "1.F" is the binary
+ number created by prefixing F with a leading 1 and a binary point.
+If E=0 and F is nonzero, then V=(-1)^S * 2^(-127) * (0.F) These are
+ "unnormalized" values.
+If E=0 and F is zero and S is 1, then V=-0
+If E=0 and F is zero and S is 0, then V=0
+
+*/
+
+#define TO_FLOAT(x) (*((float*)((void*)&x)))
+
+int __cdecl main(int argc, char **argv)
+{
+ /*non-finite numbers*/
+ UINT32 lsnan = 0xffffffffu;
+ UINT32 lqnan = 0x7fffffffu;
+ UINT32 lneginf = 0xff800000u;
+ UINT32 lposinf = 0x7f800000u;
+
+ float snan = TO_FLOAT(lsnan);
+ float qnan = TO_FLOAT(lqnan);
+ float neginf = TO_FLOAT(lneginf);
+ float posinf = TO_FLOAT(lposinf);
+
+ /*finite numbers*/
+ UINT32 lnegunnormalized = 0x807fffffu;
+ UINT32 lposunnormalized = 0x007fffffu;
+ UINT32 lnegzero = 0x80000000u;
+
+ float negunnormalized = TO_FLOAT(lnegunnormalized);
+ float posunnormalized = TO_FLOAT(lposunnormalized);
+ float negzero = TO_FLOAT(lnegzero);
+
+ /*
+ * Initialize the PAL and return FAIL if this fails
+ */
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+ /*non-finite numbers*/
+ if (_finitef(snan) || _finitef(qnan))
+ {
+ Fail("_finitef() found NAN to be finite.\n");
+ }
+
+ if (_finitef(neginf))
+ {
+ Fail("_finitef() found negative infinity to be finite.\n");
+ }
+
+ if (_finitef(posinf))
+ {
+ Fail("_finitef() found infinity to be finite.\n");
+ }
+
+ /*finite numbers*/
+ if (!_finitef(negunnormalized))
+ {
+ Fail("_finitef() found a negative unnormalized value to be infinite.\n");
+ }
+
+ if (!_finitef(posunnormalized))
+ {
+ Fail("_finitef() found an unnormalized value to be infinite.\n");
+ }
+
+ if (!_finitef(negzero))
+ {
+ Fail("_finitef() found negative zero to be infinite.\n");
+ }
+
+ if (!_finitef(+0.0f))
+ {
+ Fail("_finitef() found zero to be infinite.\n");
+ }
+
+ if (!_finitef(-123.456f))
+ {
+ Fail("_finitef() found %f to be infinite.\n", -123.456f);
+ }
+
+ if (!_finitef(+123.456f))
+ {
+ Fail("_finitef() found %f to be infinite.\n", +123.456f);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_finitef/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_finitef/test1/testinfo.dat
new file mode 100644
index 0000000000..b0767431e5
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_finitef/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _finitef
+Name = Positive Test for _finitef
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Checks that _finitef correctly classifies all types of floating point
+= numbers (NaN, -Infinity, Infinity, finite nonzero, unnormalized, 0, and -0).
diff --git a/src/pal/tests/palsuite/c_runtime/_isnanf/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_isnanf/CMakeLists.txt
new file mode 100644
index 0000000000..5e1ef7f28b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_isnanf/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
diff --git a/src/pal/tests/palsuite/c_runtime/_isnanf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_isnanf/test1/CMakeLists.txt
new file mode 100644
index 0000000000..a8d42aa975
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_isnanf/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_isnanf_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_isnanf_test1 coreclrpal)
+
+target_link_libraries(paltest_isnanf_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_isnanf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/_isnanf/test1/test1.c
new file mode 100644
index 0000000000..9b75a7236d
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_isnanf/test1/test1.c
@@ -0,0 +1,115 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose:
+** Test _isnanf with a number of trivial values, to ensure they indicated that
+** they are numbers. Then try with Positive/Negative Infinite, which should
+** also be numbers. Finally set the least and most significant bits of
+** the fraction to positive and negative, at which point it should return
+** the true value.
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+#define TO_FLOAT(x) (*((float*)((void*)&x)))
+#define TO_I32(x) (*((INT32*)((void*)&x)))
+
+/*
+ * NaN: any float with maximum exponent (0x7f8) and non-zero fraction
+ */
+int __cdecl main(int argc, char *argv[])
+{
+ /*
+ * Initialize the PAL and return FAIL if this fails
+ */
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+ /*
+ * Try some trivial values
+ */
+ if (_isnanf(0.0f))
+ {
+ Fail("_isnanf() incorrectly identified %f as NaN!\n", 0.0f);
+ }
+
+ if (_isnanf(1.234567f))
+ {
+ Fail("_isnanf() incorrectly identified %f as NaN!\n", 1.234567f);
+ }
+
+ if (_isnanf(42.0f))
+ {
+ Fail("_isnanf() incorrectly identified %f as NaN!\n", 42.0f);
+ }
+
+ UINT32 lneginf = 0xff800000u;
+ UINT32 lposinf = 0x7f800000u;
+
+ float neginf = TO_FLOAT(lneginf);
+ float posinf = TO_FLOAT(lposinf);
+
+ /*
+ * Try positive and negative infinity
+ */
+ if (_isnanf(neginf))
+ {
+ Fail("_isnanf() incorrectly identified negative infinity as NaN!\n");
+ }
+
+ if (_isnanf(posinf))
+ {
+ Fail("_isnanf() incorrectly identified infinity as NaN!\n");
+ }
+
+ /*
+ * Try setting the least significant bit of the fraction,
+ * positive and negative
+ */
+ UINT32 lsnan = 0xff800001u;
+ float snan = TO_FLOAT(lsnan);
+
+ if (!_isnanf(snan))
+ {
+ Fail("_isnanf() failed to identify %I32x as NaN!\n", lsnan);
+ }
+
+ UINT32 lqnan = 0x7f800001u;
+ float qnan = TO_FLOAT(lqnan);
+
+ if (!_isnanf(qnan))
+ {
+ Fail("_isnanf() failed to identify %I32x as NaN!\n", lqnan);
+ }
+
+ /*
+ * Try setting the most significant bit of the fraction,
+ * positive and negative
+ */
+ lsnan = 0xffc00000u;
+ snan = TO_FLOAT(lsnan);
+
+ if (!_isnanf(snan))
+ {
+ Fail ("_isnanf() failed to identify %I32x as NaN!\n", lsnan);
+ }
+
+ lqnan = 0x7fc00000u;
+ qnan = TO_FLOAT(lqnan);
+
+ if (!_isnanf(qnan))
+ {
+ Fail ("_isnanf() failed to identify %I32x as NaN!\n", lqnan);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_isnanf/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_isnanf/test1/testinfo.dat
new file mode 100644
index 0000000000..22b0edbd74
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_isnanf/test1/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _isnanf
+Name = Test #1 for _isnanf
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Test _isnanf with a number of trivial values, to ensure they indicated that
+= they are numbers. Then try with Positive/Negative Infinite, which should
+= also be numbers. Finally set the least and most significant bits of
+= the fraction to positive and negative, at which point it should return
+= the true value.
diff --git a/src/pal/tests/palsuite/c_runtime/acosf/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/acosf/CMakeLists.txt
new file mode 100644
index 0000000000..5e1ef7f28b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/acosf/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
diff --git a/src/pal/tests/palsuite/c_runtime/acosf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/acosf/test1/CMakeLists.txt
new file mode 100644
index 0000000000..2643647438
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/acosf/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_acosf_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_acosf_test1 coreclrpal)
+
+target_link_libraries(paltest_acosf_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/acosf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/acosf/test1/test1.c
new file mode 100644
index 0000000000..3d8668cebb
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/acosf/test1/test1.c
@@ -0,0 +1,129 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Test to ensure that acosf return the correct values
+**
+** Dependencies: PAL_Initialize
+** PAL_Terminate
+** Fail
+** fabs
+**
+**===========================================================================*/
+
+#include <palsuite.h>
+
+// binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this
+// is slightly too accurate when writing tests meant to run against libm implementations
+// for various platforms. 2^-21 (approx. 4.76e-07) seems to be as accurate as we can get.
+//
+// The tests themselves will take PAL_EPSILON and adjust it according to the expected result
+// so that the delta used for comparison will compare the most significant digits and ignore
+// any digits that are outside the double precision range (6-9 digits).
+
+// For example, a test with an expect result in the format of 0.xxxxxxxxx will use PAL_EPSILON
+// for the variance, while an expected result in the format of 0.0xxxxxxxxx will use
+// PAL_EPSILON / 10 and and expected result in the format of x.xxxxxx will use PAL_EPSILON * 10.
+#define PAL_EPSILON 4.76837158e-07
+
+#define PAL_NAN sqrtf(-1.0f)
+#define PAL_POSINF -logf(0.0f)
+#define PAL_NEGINF logf(0.0f)
+
+/**
+ * Helper test structure
+ */
+struct test
+{
+ float value; /* value to test the function with */
+ float expected; /* expected result */
+ float variance; /* maximum delta between the expected and actual result */
+};
+
+/**
+ * validate
+ *
+ * test validation function
+ */
+void __cdecl validate(float value, float expected, float variance)
+{
+ float result = acosf(value);
+
+ /*
+ * The test is valid when the difference between result
+ * and expected is less than or equal to variance
+ */
+ float delta = fabsf(result - expected);
+
+ if (delta > variance)
+ {
+ Fail("acosf(%g) returned %10.9g when it should have returned %10.9g",
+ value, result, expected);
+ }
+}
+
+/**
+ * validate
+ *
+ * test validation function for values returning NaN
+ */
+void __cdecl validate_isnan(float value)
+{
+ float result = acosf(value);
+
+ if (!_isnanf(result))
+ {
+ Fail("acosf(%g) returned %10.9g when it should have returned %10.9g",
+ value, result, PAL_NAN);
+ }
+}
+
+/**
+ * main
+ *
+ * executable entry point
+ */
+int __cdecl main(int argc, char **argv)
+{
+ struct test tests[] =
+ {
+ /* value expected variance */
+ { -1, 3.14159265f, PAL_EPSILON * 10 }, // expected: pi
+ { -0.911733915f, 2.71828183f, PAL_EPSILON * 10 }, // expected: e
+ { -0.668201510f, 2.30258509f, PAL_EPSILON * 10 }, // expected: ln(10)
+ { 0, 1.57079633f, PAL_EPSILON * 10 }, // expected: pi / 2
+ { 0.127751218f, 1.44269504f, PAL_EPSILON * 10 }, // expected: logf2(e)
+ { 0.155943695f, 1.41421356f, PAL_EPSILON * 10 }, // expected: sqrtf(2)
+ { 0.428125148f, 1.12837917f, PAL_EPSILON * 10 }, // expected: 2 / sqrtf(pi)
+ { 0.540302306f, 1, PAL_EPSILON * 10 },
+ { 0.707106781f, 0.785398163f, PAL_EPSILON }, // expected: pi / 4, value: 1 / sqrtf(2)
+ { 0.760244597f, 0.707106781f, PAL_EPSILON }, // expected: 1 / sqrtf(2)
+ { 0.769238901f, 0.693147181f, PAL_EPSILON }, // expected: ln(2)
+ { 0.804109828f, 0.636619772f, PAL_EPSILON }, // expected: 2 / pi
+ { 0.907167129f, 0.434294482f, PAL_EPSILON }, // expected: logf10f(e)
+ { 0.949765715f, 0.318309886f, PAL_EPSILON }, // expected: 1 / pi
+ { 1, 0, PAL_EPSILON },
+ };
+
+ /* PAL initialization */
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+ for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++)
+ {
+ validate(tests[i].value, tests[i].expected, tests[i].variance);
+ }
+
+ validate_isnan(PAL_NEGINF);
+ validate_isnan(PAL_NAN);
+ validate_isnan(PAL_POSINF);
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/acosf/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/acosf/test1/testinfo.dat
new file mode 100644
index 0000000000..41cead33bb
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/acosf/test1/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = acosf
+Name = Positive Test for acosf
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Passes a series of values to the acosf() function,
+= checking each for the expfected result. Also checks
+= for proper handling of out-of-range values.
diff --git a/src/pal/tests/palsuite/c_runtime/asinf/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/asinf/CMakeLists.txt
new file mode 100644
index 0000000000..5e1ef7f28b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/asinf/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
diff --git a/src/pal/tests/palsuite/c_runtime/asinf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/asinf/test1/CMakeLists.txt
new file mode 100644
index 0000000000..b167bd8715
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/asinf/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_asinf_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_asinf_test1 coreclrpal)
+
+target_link_libraries(paltest_asinf_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/asinf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/asinf/test1/test1.c
new file mode 100644
index 0000000000..773015eec0
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/asinf/test1/test1.c
@@ -0,0 +1,145 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Test to ensure that asinf return the correct values
+**
+** Dependencies: PAL_Initialize
+** PAL_Terminate
+** Fail
+** fabs
+**
+**===========================================================================*/
+
+#include <palsuite.h>
+
+// binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this
+// is slightly too accurate when writing tests meant to run against libm implementations
+// for various platforms. 2^-21 (approx. 4.76e-07) seems to be as accurate as we can get.
+//
+// The tests themselves will take PAL_EPSILON and adjust it according to the expected result
+// so that the delta used for comparison will compare the most significant digits and ignore
+// any digits that are outside the double precision range (6-9 digits).
+
+// For example, a test with an expect result in the format of 0.xxxxxxxxx will use PAL_EPSILON
+// for the variance, while an expected result in the format of 0.0xxxxxxxxx will use
+// PAL_EPSILON / 10 and and expected result in the format of x.xxxxxx will use PAL_EPSILON * 10.
+#define PAL_EPSILON 4.76837158e-07
+
+#define PAL_NAN sqrtf(-1.0f)
+#define PAL_POSINF -logf(0.0f)
+#define PAL_NEGINF logf(0.0f)
+
+/**
+ * Helper test structure
+ */
+struct test
+{
+ float value; /* value to test the function with */
+ float expected; /* expected result */
+ float variance; /* maximum delta between the expected and actual result */
+};
+
+/**
+ * validate
+ *
+ * test validation function
+ */
+void __cdecl validate(float value, float expected, float variance)
+{
+ float result = asinf(value);
+
+ /*
+ * The test is valid when the difference between result
+ * and expected is less than or equal to variance
+ */
+ float delta = fabsf(result - expected);
+
+ if (delta > variance)
+ {
+ Fail("asinf(%g) returned %10.9g when it should have returned %10.9g",
+ value, result, expected);
+ }
+}
+
+/**
+ * validate
+ *
+ * test validation function for values returning NaN
+ */
+void __cdecl validate_isnan(float value)
+{
+ float result = asinf(value);
+
+ if (!_isnanf(result))
+ {
+ Fail("asinf(%g) returned %10.9g when it should have returned %10.9g",
+ value, result, PAL_NAN);
+ }
+}
+
+/**
+ * validate
+ *
+ * test validation function for values returning +INF
+ */
+void __cdecl validate_isinf_positive(float value)
+{
+ float result = asinf(value);
+
+ if (result != PAL_POSINF)
+ {
+ Fail("asinf(%g) returned %10.9g when it should have returned %10.9g",
+ value, result, PAL_POSINF);
+ }
+}
+
+/**
+ * main
+ *
+ * executable entry point
+ */
+int __cdecl main(int argc, char **argv)
+{
+ struct test tests[] =
+ {
+ /* value expected variance */
+ { 0, 0, PAL_EPSILON },
+ { 0.312961796f, 0.318309886f, PAL_EPSILON }, // expected: 1 / pi
+ { 0.410781291f, 0.423310825f, PAL_EPSILON }, // expected: pi - e
+ { 0.420770483f, 0.434294482f, PAL_EPSILON }, // expected: logf10f(e)
+ { 0.594480769f, 0.636619772f, PAL_EPSILON }, // expected: 2 / pi
+ { 0.638961276f, 0.693147181f, PAL_EPSILON }, // expected: ln(2)
+ { 0.649636939f, 0.707106781f, PAL_EPSILON }, // expected: 1 / sqrtf(2)
+ { 0.707106781f, 0.785398163f, PAL_EPSILON }, // expected: pi / 4, value: 1 / sqrtf(2)
+ { 0.743980337f, 0.839007561f, PAL_EPSILON }, // expected: pi - ln(10)
+ { 0.841470985f, 1, PAL_EPSILON * 10 },
+ { 0.903719457f, 1.12837917f, PAL_EPSILON * 10 }, // expected: 2 / sqrtf(pi)
+ { 0.987765946f, 1.41421356f, PAL_EPSILON * 10 }, // expected: sqrtf(2)
+ { 0.991806244f, 1.44269504f, PAL_EPSILON * 10 }, // expected: logf2(e)
+ { 1, 1.57079633f, PAL_EPSILON * 10 }, // expected: pi / 2
+ };
+
+ /* PAL initialization */
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+ for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++)
+ {
+ validate( tests[i].value, tests[i].expected, tests[i].variance);
+ validate(-tests[i].value, -tests[i].expected, tests[i].variance);
+ }
+
+ validate_isnan(PAL_NEGINF);
+ validate_isnan(PAL_NAN);
+ validate_isnan(PAL_POSINF);
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/asinf/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/asinf/test1/testinfo.dat
new file mode 100644
index 0000000000..ca2dd42150
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/asinf/test1/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = asinf
+Name = Positive Test for asinf
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Passes a series of values to the asinf() function,
+= checking each for the expected result. Also checks
+= for proper handling of out-of-range values.
diff --git a/src/pal/tests/palsuite/c_runtime/atan2f/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/atan2f/CMakeLists.txt
new file mode 100644
index 0000000000..5e1ef7f28b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/atan2f/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
diff --git a/src/pal/tests/palsuite/c_runtime/atan2f/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/atan2f/test1/CMakeLists.txt
new file mode 100644
index 0000000000..d71a61b17b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/atan2f/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_atan2f_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_atan2f_test1 coreclrpal)
+
+target_link_libraries(paltest_atan2f_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/atan2f/test1/test1.c b/src/pal/tests/palsuite/c_runtime/atan2f/test1/test1.c
new file mode 100644
index 0000000000..2ee641e8d4
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/atan2f/test1/test1.c
@@ -0,0 +1,147 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test1.c
+**
+** Purpose: Tests that atan2f returns correct values for a subset of values.
+** Tests with positive and negative values of x and y to ensure
+** atan2f is returning results from the correct quadrant.
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+// binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this
+// is slightly too accurate when writing tests meant to run against libm implementations
+// for various platforms. 2^-21 (approx. 4.76e-07) seems to be as accurate as we can get.
+//
+// The tests themselves will take PAL_EPSILON and adjust it according to the expected result
+// so that the delta used for comparison will compare the most significant digits and ignore
+// any digits that are outside the double precision range (6-9 digits).
+
+// For example, a test with an expect result in the format of 0.xxxxxxxxx will use PAL_EPSILON
+// for the variance, while an expected result in the format of 0.0xxxxxxxxx will use
+// PAL_EPSILON / 10 and and expected result in the format of x.xxxxxx will use PAL_EPSILON * 10.
+#define PAL_EPSILON 4.76837158e-07
+
+#define PAL_NAN sqrtf(-1.0f)
+#define PAL_POSINF -logf(0.0f)
+#define PAL_NEGINF logf(0.0f)
+
+struct test
+{
+ float y; /* second component of the value to test the function with */
+ float x; /* first component of the value to test the function with */
+ float expected; /* expected result */
+ float variance; /* maximum delta between the expected and actual result */
+};
+
+/**
+ * validate
+ *
+ * test validation function
+ */
+void __cdecl validate(float y, float x, float expected, float variance)
+{
+ float result = atan2f(y, x);
+
+ /*
+ * The test is valid when the difference between result
+ * and expected is less than or equal to variance
+ */
+ float delta = fabsf(result - expected);
+
+ if (delta > variance)
+ {
+ Fail("atan2f(%g, %g) returned %10.9g when it should have returned %10.9g",
+ y, x, result, expected);
+ }
+}
+
+/**
+ * validate
+ *
+ * test validation function for values returning NaN
+ */
+void __cdecl validate_isnan(float y, float x)
+{
+ float result = atan2f(y, x);
+
+ if (!_isnanf(result))
+ {
+ Fail("atan2f(%g, %g) returned %10.9g when it should have returned %10.9g",
+ y, x, result, PAL_NAN);
+ }
+}
+
+/**
+ * main
+ *
+ * executable entry point
+ */
+int __cdecl main(int argc, char **argv)
+{
+ struct test tests[] =
+ {
+ /* y x expected variance */
+ { 0, PAL_POSINF, 0, PAL_EPSILON },
+ { 0, 0, 0, PAL_EPSILON },
+ { 0.312961796f, 0.949765715f, 0.318309886f, PAL_EPSILON }, // expected: 1 / pi
+ { 0.420770483f, 0.907167129f, 0.434294482f, PAL_EPSILON }, // expected: logf10f(e)
+ { 0.594480769f, 0.804109828f, 0.636619772f, PAL_EPSILON }, // expected: 2 / pi
+ { 0.638961276f, 0.769238901f, 0.693147181f, PAL_EPSILON }, // expected: ln(2)
+ { 0.649636939f, 0.760244597f, 0.707106781f, PAL_EPSILON }, // expected: 1 / sqrtf(2)
+ { 0.707106781f, 0.707106781f, 0.785398163f, PAL_EPSILON }, // expected: pi / 4, value: 1 / sqrtf(2)
+ { 1, 1, 0.785398163f, PAL_EPSILON }, // expected: pi / 4
+ { PAL_POSINF, PAL_POSINF, 0.785398163f, PAL_EPSILON }, // expected: pi / 4
+ { 0.841470985f, 0.540302306f, 1, PAL_EPSILON * 10 },
+ { 0.903719457f, 0.428125148f, 1.12837917f, PAL_EPSILON * 10 }, // expected: 2 / sqrtf(pi)
+ { 0.987765946f, 0.155943695f, 1.41421356f, PAL_EPSILON * 10 }, // expected: sqrtf(2)
+ { 0.991806244f, 0.127751218f, 1.44269504f, PAL_EPSILON * 10 }, // expected: logf2(e)
+ { 1, 0, 1.57079633f, PAL_EPSILON * 10 }, // expected: pi / 2
+ { PAL_POSINF, 0, 1.57079633f, PAL_EPSILON * 10 }, // expected: pi / 2
+ { PAL_POSINF, 1, 1.57079633f, PAL_EPSILON * 10 }, // expected: pi / 2
+ { 0.743980337f, -0.668201510f, 2.30258509f, PAL_EPSILON * 10 }, // expected: ln(10)
+ { 0.410781291f, -0.911733915f, 2.71828183f, PAL_EPSILON * 10 }, // expected: e
+ { 0, -1, 3.14159265f, PAL_EPSILON * 10 }, // expected: pi
+ { 1, PAL_POSINF, 0, PAL_EPSILON },
+ };
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+ for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++)
+ {
+ const float pi = 3.14159265f;
+
+ validate( tests[i].y, tests[i].x, tests[i].expected, tests[i].variance);
+ validate(-tests[i].y, tests[i].x, -tests[i].expected, tests[i].variance);
+ validate( tests[i].y, -tests[i].x, pi - tests[i].expected, tests[i].variance);
+ validate(-tests[i].y, -tests[i].x, tests[i].expected - pi, tests[i].variance);
+ }
+
+ validate_isnan(PAL_NEGINF, PAL_NAN);
+ validate_isnan(PAL_NAN, PAL_NEGINF);
+ validate_isnan(PAL_NAN, PAL_POSINF);
+ validate_isnan(PAL_POSINF, PAL_NAN);
+
+ validate_isnan(PAL_NAN, -1);
+ validate_isnan(PAL_NAN, -0.0f);
+ validate_isnan(PAL_NAN, 0);
+ validate_isnan(PAL_NAN, 1);
+
+ validate_isnan(-1, PAL_NAN);
+ validate_isnan(-0.0f, PAL_NAN);
+ validate_isnan( 0, PAL_NAN);
+ validate_isnan( 1, PAL_NAN);
+
+ validate_isnan(PAL_NAN, PAL_NAN);
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/atan2f/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/atan2f/test1/testinfo.dat
new file mode 100644
index 0000000000..bd9a9d9b93
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/atan2f/test1/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = atan2f
+Name = Test #1 for atan2f
+Type = DEFAULT
+EXE1 = test1
+Description
+=Tests that atan2f returns correct values for a subset of values.
+=Tests with positive and negative values of x and y to ensure
+=atan2f is returning results from the correct quadrant.
diff --git a/src/pal/tests/palsuite/c_runtime/atanf/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/atanf/CMakeLists.txt
new file mode 100644
index 0000000000..5e1ef7f28b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/atanf/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
diff --git a/src/pal/tests/palsuite/c_runtime/atanf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/atanf/test1/CMakeLists.txt
new file mode 100644
index 0000000000..b71b1cf40c
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/atanf/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_atanf_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_atanf_test1 coreclrpal)
+
+target_link_libraries(paltest_atanf_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/atanf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/atanf/test1/test1.c
new file mode 100644
index 0000000000..543a0a8168
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/atanf/test1/test1.c
@@ -0,0 +1,127 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Test to ensure that atanf return the correct values
+**
+** Dependencies: PAL_Initialize
+** PAL_Terminate
+** Fail
+** fabs
+**
+**===========================================================================*/
+
+#include <palsuite.h>
+
+// binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this
+// is slightly too accurate when writing tests meant to run against libm implementations
+// for various platforms. 2^-21 (approx. 4.76e-07) seems to be as accurate as we can get.
+//
+// The tests themselves will take PAL_EPSILON and adjust it according to the expected result
+// so that the delta used for comparison will compare the most significant digits and ignore
+// any digits that are outside the double precision range (6-9 digits).
+
+// For example, a test with an expect result in the format of 0.xxxxxxxxx will use PAL_EPSILON
+// for the variance, while an expected result in the format of 0.0xxxxxxxxx will use
+// PAL_EPSILON / 10 and and expected result in the format of x.xxxxxx will use PAL_EPSILON * 10.
+#define PAL_EPSILON 4.76837158e-07
+
+#define PAL_NAN sqrtf(-1.0f)
+#define PAL_POSINF -logf(0.0f)
+#define PAL_NEGINF logf(0.0f)
+
+/**
+ * Helper test structure
+ */
+struct test
+{
+ float value; /* value to test the function with */
+ float expected; /* expected result */
+ float variance; /* maximum delta between the expected and actual result */
+};
+
+/**
+ * validate
+ *
+ * test validation function
+ */
+void __cdecl validate(float value, float expected, float variance)
+{
+ float result = atanf(value);
+
+ /*
+ * The test is valid when the difference between result
+ * and expected is less than or equal to variance
+ */
+ float delta = fabsf(result - expected);
+
+ if (delta > variance)
+ {
+ Fail("atanf(%g) returned %10.9g when it should have returned %10.9g",
+ value, result, expected);
+ }
+}
+
+/**
+ * validate
+ *
+ * test validation function for values returning NaN
+ */
+void __cdecl validate_isnan(float value)
+{
+ float result = atanf(value);
+
+ if (!_isnanf(result))
+ {
+ Fail("atanf(%g) returned %10.9g when it should have returned %10.9g",
+ value, result, PAL_NAN);
+ }
+}
+
+/**
+ * main
+ *
+ * executable entry point
+ */
+int __cdecl main(int argc, char **argv)
+{
+ struct test tests[] =
+ {
+ /* value expected variance */
+ { 0, 0, PAL_EPSILON },
+ { 0.329514733f, 0.318309886f, PAL_EPSILON }, // expected: 1 / pi
+ { 0.450549534f, 0.423310825f, PAL_EPSILON }, // expected: pi - e
+ { 0.463829067f, 0.434294482f, PAL_EPSILON }, // expected: logf10f(e)
+ { 0.739302950f, 0.636619772f, PAL_EPSILON }, // expected: 2 / pi
+ { 0.830640878f, 0.693147181f, PAL_EPSILON }, // expected: ln(2)
+ { 0.854510432f, 0.707106781f, PAL_EPSILON }, // expected: 1 / sqrtf(2)
+ { 1, 0.785398163f, PAL_EPSILON }, // expected: pi / 4
+ { 1.11340715f, 0.839007561f, PAL_EPSILON }, // expected: pi - ln(10)
+ { 1.55740772f, 1, PAL_EPSILON * 10 },
+ { 2.11087684f, 1.12837917f, PAL_EPSILON * 10 }, // expected: 2 / sqrtf(pi)
+ { 6.33411917f, 1.41421356f, PAL_EPSILON * 10 }, // expected: sqrtf(2)
+ { 7.76357567f, 1.44269504f, PAL_EPSILON * 10 }, // expected: logf2(e)
+ { PAL_POSINF, 1.57079633f, PAL_EPSILON * 10 }, // expected: pi / 2
+ };
+
+ /* PAL initialization */
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+ for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++)
+ {
+ validate( tests[i].value, tests[i].expected, tests[i].variance);
+ validate(-tests[i].value, -tests[i].expected, tests[i].variance);
+ }
+
+ validate_isnan(PAL_NAN);
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/atanf/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/atanf/test1/testinfo.dat
new file mode 100644
index 0000000000..0d184272a2
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/atanf/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = atanf
+Name = Positive Test for atanf
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Passes a series of values to the atanf() function,
+= checking each for the expected result.
diff --git a/src/pal/tests/palsuite/c_runtime/ceilf/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/ceilf/CMakeLists.txt
new file mode 100644
index 0000000000..5e1ef7f28b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/ceilf/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
diff --git a/src/pal/tests/palsuite/c_runtime/ceilf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/ceilf/test1/CMakeLists.txt
new file mode 100644
index 0000000000..64f14cda9a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/ceilf/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_ceilf_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_ceilf_test1 coreclrpal)
+
+target_link_libraries(paltest_ceilf_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/ceilf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/ceilf/test1/test1.c
new file mode 100644
index 0000000000..4939fb7ccf
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/ceilf/test1/test1.c
@@ -0,0 +1,131 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Tests ceilf with simple positive and negative values. Also tests
+** extreme cases like extremely small values and positive and
+** negative infinity. Makes sure that calling ceilf on NaN returns
+** NaN
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+// binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this
+// is slightly too accurate when writing tests meant to run against libm implementations
+// for various platforms. 2^-21 (approx. 4.76e-07) seems to be as accurate as we can get.
+//
+// The tests themselves will take PAL_EPSILON and adjust it according to the expected result
+// so that the delta used for comparison will compare the most significant digits and ignore
+// any digits that are outside the double precision range (6-9 digits).
+
+// For example, a test with an expect result in the format of 0.xxxxxxxxx will use PAL_EPSILON
+// for the variance, while an expected result in the format of 0.0xxxxxxxxx will use
+// PAL_EPSILON / 10 and and expected result in the format of x.xxxxxx will use PAL_EPSILON * 10.
+#define PAL_EPSILON 4.76837158e-07
+
+#define PAL_NAN sqrtf(-1.0f)
+#define PAL_POSINF -logf(0.0f)
+#define PAL_NEGINF logf(0.0f)
+
+/**
+ * Helper test structure
+ */
+struct test
+{
+ float value; /* value to test the function with */
+ float expected; /* expected result */
+ float variance; /* maximum delta between the expected and actual result */
+};
+
+/**
+ * validate
+ *
+ * test validation function
+ */
+void __cdecl validate(float value, float expected, float variance)
+{
+ float result = ceilf(value);
+
+ /*
+ * The test is valid when the difference between result
+ * and expected is less than or equal to variance
+ */
+ float delta = fabsf(result - expected);
+
+ if (delta > variance)
+ {
+ Fail("ceilf(%g) returned %10.9g when it should have returned %10.9g",
+ value, result, expected);
+ }
+}
+
+/**
+ * validate
+ *
+ * test validation function for values returning NaN
+ */
+void __cdecl validate_isnan(float value)
+{
+ float result = ceilf(value);
+
+ if (!_isnanf(result))
+ {
+ Fail("ceilf(%g) returned %10.9g when it should have returned %10.9g",
+ value, result, PAL_NAN);
+ }
+}
+
+/**
+ * main
+ *
+ * executable entry point
+ */
+int __cdecl main(int argc, char *argv[])
+{
+ struct test tests[] =
+ {
+ /* value expected variance */
+ { 0.318309886f, 1, PAL_EPSILON * 10 }, // value: 1 / pi
+ { 0.434294482f, 1, PAL_EPSILON * 10 }, // value: log10f(e)
+ { 0.636619772f, 1, PAL_EPSILON * 10 }, // value: 2 / pi
+ { 0.693147181f, 1, PAL_EPSILON * 10 }, // value: ln(2)
+ { 0.707106781f, 1, PAL_EPSILON * 10 }, // value: 1 / sqrtf(2)
+ { 0.785398163f, 1, PAL_EPSILON * 10 }, // value: pi / 4
+ { 1.12837917f, 2, PAL_EPSILON * 10 }, // value: 2 / sqrtf(pi)
+ { 1.41421356f, 2, PAL_EPSILON * 10 }, // value: sqrtf(2)
+ { 1.44269504f, 2, PAL_EPSILON * 10 }, // value: logf2(e)
+ { 1.57079633f, 2, PAL_EPSILON * 10 }, // value: pi / 2
+ { 2.30258509f, 3, PAL_EPSILON * 10 }, // value: ln(10)
+ { 2.71828183f, 3, PAL_EPSILON * 10 }, // value: e
+ { 3.14159265f, 4, PAL_EPSILON * 10 }, // value: pi
+ { PAL_POSINF, PAL_POSINF, 0 }
+ };
+
+ /* PAL initialization */
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+ validate( 0, 0, PAL_EPSILON);
+ validate(-0.0f, 0, PAL_EPSILON);
+
+ validate( 1, 1, PAL_EPSILON * 10);
+ validate(-1.0f, -1, PAL_EPSILON * 10);
+
+ for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++)
+ {
+ validate( tests[i].value, tests[i].expected, tests[i].variance);
+ validate(-tests[i].value, 1 - tests[i].expected, tests[i].variance);
+ }
+
+ validate_isnan(PAL_NAN);
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/ceilf/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/ceilf/test1/testinfo.dat
new file mode 100644
index 0000000000..095b8b216a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/ceilf/test1/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = ceilf
+Name = Test #1 for ceilf
+TYPE = DEFAULT
+EXE1 = test1
+Description
+=Tests ceilf with simple positive and negative values. Also tests
+=extreme cases like extremely small values and positive and negative
+=infinity. Makes sure that calling ceilf on NaN returns NaN
diff --git a/src/pal/tests/palsuite/c_runtime/cosf/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/cosf/CMakeLists.txt
new file mode 100644
index 0000000000..5e1ef7f28b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/cosf/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
diff --git a/src/pal/tests/palsuite/c_runtime/cosf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/cosf/test1/CMakeLists.txt
new file mode 100644
index 0000000000..b3a18ea271
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/cosf/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_cosf_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_cosf_test1 coreclrpal)
+
+target_link_libraries(paltest_cosf_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/cosf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/cosf/test1/test1.c
new file mode 100644
index 0000000000..210851a2fa
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/cosf/test1/test1.c
@@ -0,0 +1,130 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Test to ensure that cosf return the correct values
+**
+** Dependencies: PAL_Initialize
+** PAL_Terminate
+** Fail
+** fabs
+**
+**===========================================================================*/
+
+#include <palsuite.h>
+
+// binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this
+// is slightly too accurate when writing tests meant to run against libm implementations
+// for various platforms. 2^-21 (approx. 4.76e-07) seems to be as accurate as we can get.
+//
+// The tests themselves will take PAL_EPSILON and adjust it according to the expected result
+// so that the delta used for comparison will compare the most significant digits and ignore
+// any digits that are outside the double precision range (6-9 digits).
+
+// For example, a test with an expect result in the format of 0.xxxxxxxxx will use PAL_EPSILON
+// for the variance, while an expected result in the format of 0.0xxxxxxxxx will use
+// PAL_EPSILON / 10 and and expected result in the format of x.xxxxxx will use PAL_EPSILON * 10.
+#define PAL_EPSILON 4.76837158e-07
+
+#define PAL_NAN sqrtf(-1.0f)
+#define PAL_POSINF -logf(0.0f)
+#define PAL_NEGINF logf(0.0f)
+
+/**
+ * Helper test structure
+ */
+struct test
+{
+ float value; /* value to test the function with */
+ float expected; /* expected result */
+ float variance; /* maximum delta between the expected and actual result */
+};
+
+/**
+ * validate
+ *
+ * test validation function
+ */
+void __cdecl validate(float value, float expected, float variance)
+{
+ float result = cosf(value);
+
+ /*
+ * The test is valid when the difference between result
+ * and expected is less than or equal to variance
+ */
+ float delta = fabsf(result - expected);
+
+ if (delta > variance)
+ {
+ Fail("cosf(%g) returned %10.9g when it should have returned %10.9g",
+ value, result, expected);
+ }
+}
+
+/**
+ * validate
+ *
+ * test validation function for values returning NaN
+ */
+void __cdecl validate_isnan(float value)
+{
+ float result = cosf(value);
+
+ if (!_isnanf(result))
+ {
+ Fail("cosf(%g) returned %10.9g when it should have returned %10.9g",
+ value, result, PAL_NAN);
+ }
+}
+
+/**
+ * main
+ *
+ * executable entry point
+ */
+int __cdecl main(int argc, char **argv)
+{
+ struct test tests[] =
+ {
+ /* value expected variance */
+ { 0, 1, PAL_EPSILON * 10 },
+ { 0.318309886f, 0.949765715f, PAL_EPSILON }, // value: 1 / pi
+ { 0.434294482f, 0.907167129f, PAL_EPSILON }, // value: log10f(e)
+ { 0.636619772f, 0.804109828f, PAL_EPSILON }, // value: 2 / pi
+ { 0.693147181f, 0.769238901f, PAL_EPSILON }, // value: ln(2)
+ { 0.707106781f, 0.760244597f, PAL_EPSILON }, // value: 1 / sqrtf(2)
+ { 0.785398163f, 0.707106781f, PAL_EPSILON }, // value: pi / 4, expected: 1 / sqrtf(2)
+ { 1, 0.540302306f, PAL_EPSILON },
+ { 1.12837917f, 0.428125148f, PAL_EPSILON }, // value: 2 / sqrtf(pi)
+ { 1.41421356f, 0.155943695f, PAL_EPSILON }, // value: sqrtf(2)
+ { 1.44269504f, 0.127751218f, PAL_EPSILON }, // value: logf2(e)
+ { 1.57079633f, 0, PAL_EPSILON }, // value: pi / 2
+ { 2.30258509f, -0.668201510f, PAL_EPSILON }, // value: ln(10)
+ { 2.71828183f, -0.911733918f, PAL_EPSILON }, // value: e
+ { 3.14159265f, -1, PAL_EPSILON * 10 }, // value: pi
+ };
+
+ /* PAL initialization */
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+ for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++)
+ {
+ validate( tests[i].value, tests[i].expected, tests[i].variance);
+ validate(-tests[i].value, tests[i].expected, tests[i].variance);
+ }
+
+ validate_isnan(PAL_NEGINF);
+ validate_isnan(PAL_NAN);
+ validate_isnan(PAL_POSINF);
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/cosf/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/cosf/test1/testinfo.dat
new file mode 100644
index 0000000000..a0265add2f
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/cosf/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = cosf
+Name = Positive Test for cosf
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Passes to cosf() a series of angle value, checking that
+= each one return the correct value.
diff --git a/src/pal/tests/palsuite/c_runtime/coshf/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/coshf/CMakeLists.txt
new file mode 100644
index 0000000000..5e1ef7f28b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/coshf/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
diff --git a/src/pal/tests/palsuite/c_runtime/coshf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/coshf/test1/CMakeLists.txt
new file mode 100644
index 0000000000..92fcfdea6d
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/coshf/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_coshf_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_coshf_test1 coreclrpal)
+
+target_link_libraries(paltest_coshf_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/coshf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/coshf/test1/test1.c
new file mode 100644
index 0000000000..e1ab745acb
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/coshf/test1/test1.c
@@ -0,0 +1,129 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Test to ensure that coshf return the correct values
+**
+** Dependencies: PAL_Initialize
+** PAL_Terminate
+** Fail
+** fabs
+**
+**===========================================================================*/
+
+#include <palsuite.h>
+
+// binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this
+// is slightly too accurate when writing tests meant to run against libm implementations
+// for various platforms. 2^-21 (approx. 4.76e-07) seems to be as accurate as we can get.
+//
+// The tests themselves will take PAL_EPSILON and adjust it according to the expected result
+// so that the delta used for comparison will compare the most significant digits and ignore
+// any digits that are outside the double precision range (6-9 digits).
+
+// For example, a test with an expect result in the format of 0.xxxxxxxxx will use PAL_EPSILON
+// for the variance, while an expected result in the format of 0.0xxxxxxxxx will use
+// PAL_EPSILON / 10 and and expected result in the format of x.xxxxxx will use PAL_EPSILON * 10.
+#define PAL_EPSILON 4.76837158e-07
+
+#define PAL_NAN sqrtf(-1.0f)
+#define PAL_POSINF -logf(0.0f)
+#define PAL_NEGINF logf(0.0f)
+
+/**
+ * Helper test structure
+ */
+struct test
+{
+ float value; /* value to test the function with */
+ float expected; /* expected result */
+ float variance; /* maximum delta between the expected and actual result */
+};
+
+/**
+ * validate
+ *
+ * test validation function
+ */
+void __cdecl validate(float value, float expected, float variance)
+{
+ float result = coshf(value);
+
+ /*
+ * The test is valid when the difference between result
+ * and expected is less than or equal to variance
+ */
+ float delta = fabsf(result - expected);
+
+ if (delta > variance)
+ {
+ Fail("coshf(%g) returned %10.9g when it should have returned %10.9g",
+ value, result, expected);
+ }
+}
+
+/**
+ * validate
+ *
+ * test validation function for values returning PAL_NAN
+ */
+void __cdecl validate_isnan(float value)
+{
+ float result = coshf(value);
+
+ if (!_isnanf(result))
+ {
+ Fail("coshf(%g) returned %10.9g when it should have returned %10.9g",
+ value, result, PAL_NAN);
+ }
+}
+
+/**
+ * main
+ *
+ * executable entry point
+ */
+int __cdecl main(int argc, char **argv)
+{
+ struct test tests[] =
+ {
+ /* value expected variance */
+ { 0, 1, PAL_EPSILON * 10 },
+ { 0.318309886f, 1.05108979f, PAL_EPSILON * 10 }, // value: 1 / pi
+ { 0.434294482f, 1.09579746f, PAL_EPSILON * 10 }, // value: log10f(e)
+ { 0.636619772f, 1.20957949f, PAL_EPSILON * 10 }, // value: 2 / pi
+ { 0.693147181f, 1.25f, PAL_EPSILON * 10 }, // value: ln(2)
+ { 0.707106781f, 1.26059184f, PAL_EPSILON * 10 }, // value: 1 / sqrtf(2)
+ { 0.785398163f, 1.32460909f, PAL_EPSILON * 10 }, // value: pi / 4
+ { 1, 1.54308063f, PAL_EPSILON * 10 },
+ { 1.12837917f, 1.70710014f, PAL_EPSILON * 10 }, // value: 2 / sqrtf(pi)
+ { 1.41421356f, 2.17818356f, PAL_EPSILON * 10 }, // value: sqrtf(2)
+ { 1.44269504f, 2.23418810f, PAL_EPSILON * 10 }, // value: logf2(e)
+ { 1.57079633f, 2.50917848f, PAL_EPSILON * 10 }, // value: pi / 2
+ { 2.30258509f, 5.05f, PAL_EPSILON * 10 }, // value: ln(10)
+ { 2.71828183f, 7.61012514f, PAL_EPSILON * 10 }, // value: e
+ { 3.14159265f, 11.5919533f, PAL_EPSILON * 100 }, // value: pi
+ { PAL_POSINF, PAL_POSINF, 0 },
+ };
+
+ /* PAL initialization */
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+ for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++)
+ {
+ validate( tests[i].value, tests[i].expected, tests[i].variance);
+ validate(-tests[i].value, tests[i].expected, tests[i].variance);
+ }
+
+ validate_isnan(PAL_NAN);
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/coshf/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/coshf/test1/testinfo.dat
new file mode 100644
index 0000000000..814ed98698
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/coshf/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = coshf
+Name = Positive Test for coshf
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Passes to coshf() a series of angle value, checking that
+= each one return to correct value.
diff --git a/src/pal/tests/palsuite/c_runtime/expf/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/expf/CMakeLists.txt
new file mode 100644
index 0000000000..5e1ef7f28b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/expf/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
diff --git a/src/pal/tests/palsuite/c_runtime/expf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/expf/test1/CMakeLists.txt
new file mode 100644
index 0000000000..fb12b65c2f
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/expf/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_expf_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_expf_test1 coreclrpal)
+
+target_link_libraries(paltest_expf_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/expf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/expf/test1/test1.c
new file mode 100644
index 0000000000..32f4e8d26c
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/expf/test1/test1.c
@@ -0,0 +1,137 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test1.c
+**
+** Purpose: Tests expf with a normal set of values.
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+// binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this
+// is slightly too accurate when writing tests meant to run against libm implementations
+// for various platforms. 2^-21 (approx. 4.76e-07) seems to be as accurate as we can get.
+//
+// The tests themselves will take PAL_EPSILON and adjust it according to the expected result
+// so that the delta used for comparison will compare the most significant digits and ignore
+// any digits that are outside the double precision range (6-9 digits).
+
+// For example, a test with an expect result in the format of 0.xxxxxxxxx will use PAL_EPSILON
+// for the variance, while an expected result in the format of 0.0xxxxxxxxx will use
+// PAL_EPSILON / 10 and and expected result in the format of x.xxxxxx will use PAL_EPSILON * 10.
+#define PAL_EPSILON 4.76837158e-07
+
+#define PAL_NAN sqrtf(-1.0f)
+#define PAL_POSINF -logf(0.0f)
+#define PAL_NEGINF logf(0.0f)
+
+/**
+ * Helper test structure
+ */
+struct test
+{
+ float value; /* value to test the function with */
+ float expected; /* expected result */
+ float variance; /* maximum delta between the expected and actual result */
+};
+
+/**
+ * validate
+ *
+ * test validation function
+ */
+void __cdecl validate(float value, float expected, float variance)
+{
+ float result = expf(value);
+
+ /*
+ * The test is valid when the difference between result
+ * and expected is less than or equal to variance
+ */
+ float delta = fabsf(result - expected);
+
+ if (delta > variance)
+ {
+ Fail("expf(%g) returned %10.9g when it should have returned %10.9g",
+ value, result, expected);
+ }
+}
+
+/**
+ * validate
+ *
+ * test validation function for values returning NaN
+ */
+void __cdecl validate_isnan(float value)
+{
+ float result = expf(value);
+
+ if (!_isnanf(result))
+ {
+ Fail("expf(%g) returned %10.9g when it should have returned %10.9g",
+ value, result, PAL_NAN);
+ }
+}
+
+/**
+ * main
+ *
+ * executable entry point
+ */
+int __cdecl main(int argc, char **argv)
+{
+ struct test tests[] =
+ {
+ /* value expected variance */
+ { PAL_NEGINF, 0, PAL_EPSILON },
+ { -3.14159265f, 0.0432139183f, PAL_EPSILON / 10 }, // value: -(pi)
+ { -2.71828183f, 0.0659880358f, PAL_EPSILON / 10 }, // value: -(e)
+ { -2.30258509f, 0.1f, PAL_EPSILON }, // value: -(ln(10))
+ { -1.57079633f, 0.207879576f, PAL_EPSILON }, // value: -(pi / 2)
+ { -1.44269504f, 0.236290088f, PAL_EPSILON }, // value: -(logf2(e))
+ { -1.41421356f, 0.243116734f, PAL_EPSILON }, // value: -(sqrtf(2))
+ { -1.12837917f, 0.323557264f, PAL_EPSILON }, // value: -(2 / sqrtf(pi))
+ { -1, 0.367879441f, PAL_EPSILON }, // value: -(1)
+ { -0.785398163f, 0.455938128f, PAL_EPSILON }, // value: -(pi / 4)
+ { -0.707106781f, 0.493068691f, PAL_EPSILON }, // value: -(1 / sqrtf(2))
+ { -0.693147181f, 0.5f, PAL_EPSILON }, // value: -(ln(2))
+ { -0.636619772f, 0.529077808f, PAL_EPSILON }, // value: -(2 / pi)
+ { -0.434294482f, 0.647721485f, PAL_EPSILON }, // value: -(log10f(e))
+ { -0.318309886f, 0.727377349f, PAL_EPSILON }, // value: -(1 / pi)
+ { 0, 1, PAL_EPSILON * 10 },
+ { 0.318309886f, 1.37480223f, PAL_EPSILON * 10 }, // value: 1 / pi
+ { 0.434294482f, 1.54387344f, PAL_EPSILON * 10 }, // value: log10f(e)
+ { 0.636619772f, 1.89008116f, PAL_EPSILON * 10 }, // value: 2 / pi
+ { 0.693147181f, 2, PAL_EPSILON * 10 }, // value: ln(2)
+ { 0.707106781f, 2.02811498f, PAL_EPSILON * 10 }, // value: 1 / sqrtf(2)
+ { 0.785398163f, 2.19328005f, PAL_EPSILON * 10 }, // value: pi / 4
+ { 1, 2.71828183f, PAL_EPSILON * 10 }, // expected: e
+ { 1.12837917f, 3.09064302f, PAL_EPSILON * 10 }, // value: 2 / sqrtf(pi)
+ { 1.41421356f, 4.11325038f, PAL_EPSILON * 10 }, // value: sqrtf(2)
+ { 1.44269504f, 4.23208611f, PAL_EPSILON * 10 }, // value: logf2(e)
+ { 1.57079633f, 4.81047738f, PAL_EPSILON * 10 }, // value: pi / 2
+ { 2.30258509f, 10, PAL_EPSILON * 100 }, // value: ln(10)
+ { 2.71828183f, 15.1542622f, PAL_EPSILON * 100 }, // value: e
+ { 3.14159265f, 23.1406926f, PAL_EPSILON * 100 }, // value: pi
+ { PAL_POSINF, PAL_POSINF, 0 },
+ };
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+ for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++)
+ {
+ validate(tests[i].value, tests[i].expected, tests[i].variance);
+ }
+
+ validate_isnan(PAL_NAN);
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/expf/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/expf/test1/testinfo.dat
new file mode 100644
index 0000000000..c35928501e
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/expf/test1/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = expf
+Name = Test #1 for expf
+Type = DEFAULT
+EXE1 = test1
+Description
+=Tests expf with a normal set of values.
diff --git a/src/pal/tests/palsuite/c_runtime/floorf/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/floorf/CMakeLists.txt
new file mode 100644
index 0000000000..5e1ef7f28b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/floorf/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
diff --git a/src/pal/tests/palsuite/c_runtime/floorf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/floorf/test1/CMakeLists.txt
new file mode 100644
index 0000000000..f6e24adcd9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/floorf/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_floorf_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_floorf_test1 coreclrpal)
+
+target_link_libraries(paltest_floorf_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/floorf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/floorf/test1/test1.c
new file mode 100644
index 0000000000..57dca21382
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/floorf/test1/test1.c
@@ -0,0 +1,131 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Tests floorf with simple positive and negative values. Also tests
+** extreme cases like extremely small values and positive and
+** negative infinity. Makes sure that calling floorf on NaN returns
+** NaN
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+// binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this
+// is slightly too accurate when writing tests meant to run against libm implementations
+// for various platforms. 2^-21 (approx. 4.76e-07) seems to be as accurate as we can get.
+//
+// The tests themselves will take PAL_EPSILON and adjust it according to the expected result
+// so that the delta used for comparison will compare the most significant digits and ignore
+// any digits that are outside the double precision range (6-9 digits).
+
+// For example, a test with an expect result in the format of 0.xxxxxxxxx will use PAL_EPSILON
+// for the variance, while an expected result in the format of 0.0xxxxxxxxx will use
+// PAL_EPSILON / 10 and and expected result in the format of x.xxxxxx will use PAL_EPSILON * 10.
+#define PAL_EPSILON 4.76837158e-07
+
+#define PAL_NAN sqrtf(-1.0f)
+#define PAL_POSINF -logf(0.0f)
+#define PAL_NEGINF logf(0.0f)
+
+/**
+ * Helper test structure
+ */
+struct test
+{
+ float value; /* value to test the function with */
+ float expected; /* expected result */
+ float variance; /* maximum delta between the expected and actual result */
+};
+
+/**
+ * validate
+ *
+ * test validation function
+ */
+void __cdecl validate(float value, float expected, float variance)
+{
+ float result = floorf(value);
+
+ /*
+ * The test is valid when the difference between result
+ * and expected is less than or equal to variance
+ */
+ float delta = fabsf(result - expected);
+
+ if (delta > variance)
+ {
+ Fail("floorf(%g) returned %10.9g when it should have returned %10.9g",
+ value, result, expected);
+ }
+}
+
+/**
+ * validate
+ *
+ * test validation function for values returning NaN
+ */
+void __cdecl validate_isnan(float value)
+{
+ float result = floorf(value);
+
+ if (!_isnanf(result))
+ {
+ Fail("floorf(%g) returned %10.9g when it should have returned %10.9g",
+ value, result, PAL_NAN);
+ }
+}
+
+/**
+ * main
+ *
+ * executable entry point
+ */
+int __cdecl main(int argc, char *argv[])
+{
+ struct test tests[] =
+ {
+ /* value expected variance */
+ { 0.318309886f, 0, PAL_EPSILON }, // value: 1 / pi
+ { 0.434294482f, 0, PAL_EPSILON }, // value: log10f(e)
+ { 0.636619772f, 0, PAL_EPSILON }, // value: 2 / pi
+ { 0.693147181f, 0, PAL_EPSILON }, // value: ln(2)
+ { 0.707106781f, 0, PAL_EPSILON }, // value: 1 / sqrtf(2)
+ { 0.785398163f, 0, PAL_EPSILON }, // value: pi / 4
+ { 1.12837917f, 1, PAL_EPSILON * 10 }, // value: 2 / sqrtf(pi)
+ { 1.41421356f, 1, PAL_EPSILON * 10 }, // value: sqrtf(2)
+ { 1.44269504f, 1, PAL_EPSILON * 10 }, // value: logf2(e)
+ { 1.57079633f, 1, PAL_EPSILON * 10 }, // value: pi / 2
+ { 2.30258509f, 2, PAL_EPSILON * 10 }, // value: ln(10)
+ { 2.71828183f, 2, PAL_EPSILON * 10 }, // value: e
+ { 3.14159265f, 3, PAL_EPSILON * 10 }, // value: pi
+ { PAL_POSINF, PAL_POSINF, 0 }
+ };
+
+ /* PAL initialization */
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+ validate( 0, 0, PAL_EPSILON);
+ validate(-0.0f, 0, PAL_EPSILON);
+
+ validate( 1, 1, PAL_EPSILON * 10);
+ validate(-1.0f, -1, PAL_EPSILON * 10);
+
+ for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++)
+ {
+ validate( tests[i].value, tests[i].expected, tests[i].variance);
+ validate(-tests[i].value, -(tests[i].expected + 1), tests[i].variance);
+ }
+
+ validate_isnan(PAL_NAN);
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/floorf/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/floorf/test1/testinfo.dat
new file mode 100644
index 0000000000..006540141a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/floorf/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = floorf
+Name = Positive Test for floorf
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Passes to floorf() a series of value, checking that
+= each one return to correct value.
diff --git a/src/pal/tests/palsuite/c_runtime/log10f/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/log10f/CMakeLists.txt
new file mode 100644
index 0000000000..5e1ef7f28b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/log10f/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
diff --git a/src/pal/tests/palsuite/c_runtime/log10f/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/log10f/test1/CMakeLists.txt
new file mode 100644
index 0000000000..b2c0835451
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/log10f/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_log10f_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_log10f_test1 coreclrpal)
+
+target_link_libraries(paltest_log10f_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/log10f/test1/test1.c b/src/pal/tests/palsuite/c_runtime/log10f/test1/test1.c
new file mode 100644
index 0000000000..e7c8c2f28b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/log10f/test1/test1.c
@@ -0,0 +1,144 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Test to ensure that log10f returns correct values.
+**
+** Dependencies: PAL_Initialize
+** PAL_Terminate
+** Fail
+** fabs
+** _isnanf
+**
+**===========================================================================*/
+
+#include <palsuite.h>
+
+// binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this
+// is slightly too accurate when writing tests meant to run against libm implementations
+// for various platforms. 2^-21 (approx. 4.76e-07) seems to be as accurate as we can get.
+//
+// The tests themselves will take PAL_EPSILON and adjust it according to the expected result
+// so that the delta used for comparison will compare the most significant digits and ignore
+// any digits that are outside the double precision range (6-9 digits).
+
+// For example, a test with an expect result in the format of 0.xxxxxxxxx will use PAL_EPSILON
+// for the variance, while an expected result in the format of 0.0xxxxxxxxx will use
+// PAL_EPSILON / 10 and and expected result in the format of x.xxxxxx will use PAL_EPSILON * 10.
+#define PAL_EPSILON 4.76837158e-07
+
+#define PAL_NAN sqrtf(-1.0f)
+#define PAL_POSINF -logf(0.0f)
+#define PAL_NEGINF logf(0.0f)
+
+/**
+ * Helper test structure
+ */
+struct test
+{
+ float value; /* value to test the function with */
+ float expected; /* expected result */
+ float variance; /* maximum delta between the expected and actual result */
+};
+
+/**
+ * validate
+ *
+ * test validation function
+ */
+void __cdecl validate(float value, float expected, float variance)
+{
+ float result = log10f(value);
+
+ /*
+ * The test is valid when the difference between result
+ * and expected is less than or equal to variance
+ */
+ float delta = fabsf(result - expected);
+
+ if (delta > variance)
+ {
+ Fail("log10f(%g) returned %10.9g when it should have returned %10.9g",
+ value, result, expected);
+ }
+}
+
+/**
+ * validate
+ *
+ * test validation function for values returning NaN
+ */
+void __cdecl validate_isnan(float value)
+{
+ float result = log10f(value);
+
+ if (!_isnanf(result))
+ {
+ Fail("log10f(%g) returned %10.9g when it should have returned %10.9g",
+ value, result, PAL_NAN);
+ }
+}
+
+/**
+ * main
+ *
+ * executable entry point
+ */
+int __cdecl main(int argc, char **argv)
+{
+ struct test tests[] =
+ {
+ /* value expected variance */
+ { 0, PAL_NEGINF, 0 },
+ { 0.000721784159f, -3.14159265f, PAL_EPSILON * 10 }, // expected: -(pi)
+ { 0.00191301410f, -2.71828183f, PAL_EPSILON * 10 }, // expected: -(e)
+ { 0.00498212830f, -2.30258509f, PAL_EPSILON * 10 }, // expected: -(ln(10))
+ { 0.0268660410f, -1.57079633f, PAL_EPSILON * 10 }, // expected: -(pi / 2)
+ { 0.0360831928f, -1.44269504f, PAL_EPSILON * 10 }, // expected: -(logf2(e))
+ { 0.0385288847f, -1.41421356f, PAL_EPSILON * 10 }, // expected: -(sqrtf(2))
+ { 0.0744082059f, -1.12837917f, PAL_EPSILON * 10 }, // expected: -(2 / sqrtf(pi))
+ { 0.1f, -1, PAL_EPSILON * 10 }, // expected: -(1)
+ { 0.163908636f, -0.785398163f, PAL_EPSILON }, // expected: -(pi / 4)
+ { 0.196287760f, -0.707106781f, PAL_EPSILON }, // expected: -(1 / sqrtf(2))
+ { 0.202699566f, -0.693147181f, PAL_EPSILON }, // expected: -(ln(2))
+ { 0.230876765f, -0.636619772f, PAL_EPSILON }, // expected: -(2 / pi)
+ { 0.367879441f, -0.434294482f, PAL_EPSILON }, // expected: -(log10f(e))
+ { 0.480496373f, -0.318309886f, PAL_EPSILON }, // expected: -(1 / pi)
+ { 1, 0, PAL_EPSILON },
+ { 2.08118116f, 0.318309886f, PAL_EPSILON }, // expected: 1 / pi
+ { 2.71828183f, 0.434294482f, PAL_EPSILON }, // expected: log10f(e) value: e
+ { 4.33131503f, 0.636619772f, PAL_EPSILON }, // expected: 2 / pi
+ { 4.93340967f, 0.693147181f, PAL_EPSILON }, // expected: ln(2)
+ { 5.09456117f, 0.707106781f, PAL_EPSILON }, // expected: 1 / sqrtf(2)
+ { 6.10095980f, 0.785398163f, PAL_EPSILON }, // expected: pi / 4
+ { 10, 1, PAL_EPSILON * 10 },
+ { 13.4393779f, 1.12837917f, PAL_EPSILON * 10 }, // expected: 2 / sqrtf(pi)
+ { 25.9545535f, 1.41421356f, PAL_EPSILON * 10 }, // expected: sqrtf(2)
+ { 27.7137338f, 1.44269504f, PAL_EPSILON * 10 }, // expected: logf2(e)
+ { 37.2217105f, 1.57079633f, PAL_EPSILON * 10 }, // expected: pi / 2
+ { 200.717432f, 2.30258509f, PAL_EPSILON * 10 }, // expected: ln(10)
+ { 522.735300f, 2.71828183f, PAL_EPSILON * 10 }, // expected: e
+ { 1385.45573f, 3.14159265f, PAL_EPSILON * 10 }, // expected: pi
+ { PAL_POSINF, PAL_POSINF, 0 },
+ };
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+ for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++)
+ {
+ validate(tests[i].value, tests[i].expected, tests[i].variance);
+ }
+
+ validate_isnan(PAL_NEGINF);
+ validate_isnan(PAL_NAN);
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/log10f/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/log10f/test1/testinfo.dat
new file mode 100644
index 0000000000..175ee3ab09
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/log10f/test1/testinfo.dat
@@ -0,0 +1,17 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = log10f
+Name = Positive Test for log10f
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Passes a series of values to the log10f() function,
+= checking each for the expected result. Also checks
+= for proper handling of out-of-range values.
+
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/logf/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/logf/CMakeLists.txt
new file mode 100644
index 0000000000..5e1ef7f28b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/logf/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
diff --git a/src/pal/tests/palsuite/c_runtime/logf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/logf/test1/CMakeLists.txt
new file mode 100644
index 0000000000..550f572bc7
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/logf/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_logf_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_logf_test1 coreclrpal)
+
+target_link_libraries(paltest_logf_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/logf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/logf/test1/test1.c
new file mode 100644
index 0000000000..499778e992
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/logf/test1/test1.c
@@ -0,0 +1,139 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test1.c
+**
+** Purpose: Tests logf with a normal set of values.
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+// binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this
+// is slightly too accurate when writing tests meant to run against libm implementations
+// for various platforms. 2^-21 (approx. 4.76e-07) seems to be as accurate as we can get.
+//
+// The tests themselves will take PAL_EPSILON and adjust it according to the expected result
+// so that the delta used for comparison will compare the most significant digits and ignore
+// any digits that are outside the double precision range (6-9 digits).
+
+// For example, a test with an expect result in the format of 0.xxxxxxxxx will use PAL_EPSILON
+// for the variance, while an expected result in the format of 0.0xxxxxxxxx will use
+// PAL_EPSILON / 10 and and expected result in the format of x.xxxxxx will use PAL_EPSILON * 10.
+#define PAL_EPSILON 4.76837158e-07
+
+#define PAL_NAN sqrtf(-1.0f)
+#define PAL_POSINF -logf(0.0f)
+#define PAL_NEGINF logf(0.0f)
+
+/**
+ * Helper test structure
+ */
+struct test
+{
+ float value; /* value to test the function with */
+ float expected; /* expected result */
+ float variance; /* maximum delta between the expected and actual result */
+};
+
+/**
+ * validate
+ *
+ * test validation function
+ */
+void __cdecl validate(float value, float expected, float variance)
+{
+ float result = logf(value);
+
+ /*
+ * The test is valid when the difference between result
+ * and expected is less than or equal to variance
+ */
+ float delta = fabsf(result - expected);
+
+ if (delta > variance)
+ {
+ Fail("logf(%g) returned %10.9g when it should have returned %10.9g",
+ value, result, expected);
+ }
+}
+
+/**
+ * validate
+ *
+ * test validation function for values returning NaN
+ */
+void __cdecl validate_isnan(float value)
+{
+ float result = logf(value);
+
+ if (!_isnanf(result))
+ {
+ Fail("logf(%g) returned %10.9g when it should have returned %10.9g",
+ value, result, PAL_NAN);
+ }
+}
+
+/**
+ * main
+ *
+ * executable entry point
+ */
+int __cdecl main(int argc, char **argv)
+{
+ struct test tests[] =
+ {
+ /* value expected variance */
+ { 0, PAL_NEGINF, 0 },
+ { 0.0432139183f, -3.14159265f, PAL_EPSILON * 10 }, // expected: -(pi)
+ { 0.0659880358f, -2.71828183f, PAL_EPSILON * 10 }, // expected: -(e)
+ { 0.1f, -2.30258509f, PAL_EPSILON * 10 }, // expected: -(ln(10))
+ { 0.207879576f, -1.57079633f, PAL_EPSILON * 10 }, // expected: -(pi / 2)
+ { 0.236290088f, -1.44269504f, PAL_EPSILON * 10 }, // expected: -(logf2(e))
+ { 0.243116734f, -1.41421356f, PAL_EPSILON * 10 }, // expected: -(sqrtf(2))
+ { 0.323557264f, -1.12837917f, PAL_EPSILON * 10 }, // expected: -(2 / sqrtf(pi))
+ { 0.367879441f, -1, PAL_EPSILON * 10 }, // expected: -(1)
+ { 0.455938128f, -0.785398163f, PAL_EPSILON }, // expected: -(pi / 4)
+ { 0.493068691f, -0.707106781f, PAL_EPSILON }, // expected: -(1 / sqrtf(2))
+ { 0.5f, -0.693147181f, PAL_EPSILON }, // expected: -(ln(2))
+ { 0.529077808f, -0.636619772f, PAL_EPSILON }, // expected: -(2 / pi)
+ { 0.647721485f, -0.434294482f, PAL_EPSILON }, // expected: -(log10f(e))
+ { 0.727377349f, -0.318309886f, PAL_EPSILON }, // expected: -(1 / pi)
+ { 1, 0, PAL_EPSILON },
+ { 1.37480223f, 0.318309886f, PAL_EPSILON }, // expected: 1 / pi
+ { 1.54387344f, 0.434294482f, PAL_EPSILON }, // expected: log10f(e)
+ { 1.89008116f, 0.636619772f, PAL_EPSILON }, // expected: 2 / pi
+ { 2, 0.693147181f, PAL_EPSILON }, // expected: ln(2)
+ { 2.02811498f, 0.707106781f, PAL_EPSILON }, // expected: 1 / sqrtf(2)
+ { 2.19328005f, 0.785398163f, PAL_EPSILON }, // expected: pi / 4
+ { 2.71828183f, 1, PAL_EPSILON * 10 }, // value: e
+ { 3.09064302f, 1.12837917f, PAL_EPSILON * 10 }, // expected: 2 / sqrtf(pi)
+ { 4.11325038f, 1.41421356f, PAL_EPSILON * 10 }, // expected: sqrtf(2)
+ { 4.23208611f, 1.44269504f, PAL_EPSILON * 10 }, // expected: logf2(e)
+ { 4.81047738f, 1.57079633f, PAL_EPSILON * 10 }, // expected: pi / 2
+ { 10, 2.30258509f, PAL_EPSILON * 10 }, // expected: ln(10)
+ { 15.1542622f, 2.71828183f, PAL_EPSILON * 10 }, // expected: e
+ { 23.1406926f, 3.14159265f, PAL_EPSILON * 10 }, // expected: pi
+ { PAL_POSINF, PAL_POSINF, 0 },
+ };
+
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+ for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++)
+ {
+ validate(tests[i].value, tests[i].expected, tests[i].variance);
+ }
+
+ validate_isnan(PAL_NEGINF);
+ validate_isnan(PAL_NAN);
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/logf/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/logf/test1/testinfo.dat
new file mode 100644
index 0000000000..aadfee6c11
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/logf/test1/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = logf
+Name = Positive Test for logf
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Passes a series of values to the logf() function,
+= checking each for the expected result. Also checks
+= for proper handling of out-of-range values.
diff --git a/src/pal/tests/palsuite/c_runtime/powf/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/powf/CMakeLists.txt
new file mode 100644
index 0000000000..5e1ef7f28b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/powf/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
diff --git a/src/pal/tests/palsuite/c_runtime/powf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/powf/test1/CMakeLists.txt
new file mode 100644
index 0000000000..8ea040f9a4
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/powf/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_powf_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_powf_test1 coreclrpal)
+
+target_link_libraries(paltest_powf_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/powf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/powf/test1/test1.c
new file mode 100644
index 0000000000..ca738e8c8d
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/powf/test1/test1.c
@@ -0,0 +1,229 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test1.c
+**
+** Purpose: Tests that atan2f returns correct values for a subset of values.
+** Tests with positive and negative values of x and y to ensure
+** atan2f is returning results from the correct quadrant.
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+// binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this
+// is slightly too accurate when writing tests meant to run against libm implementations
+// for various platforms. 2^-21 (approx. 4.76e-07) seems to be as accurate as we can get.
+//
+// The tests themselves will take PAL_EPSILON and adjust it according to the expected result
+// so that the delta used for comparison will compare the most significant digits and ignore
+// any digits that are outside the double precision range (6-9 digits).
+
+// For example, a test with an expect result in the format of 0.xxxxxxxxx will use PAL_EPSILON
+// for the variance, while an expected result in the format of 0.0xxxxxxxxx will use
+// PAL_EPSILON / 10 and and expected result in the format of x.xxxxxx will use PAL_EPSILON * 10.
+#define PAL_EPSILON 4.76837158e-07
+
+#define PAL_NAN sqrtf(-1.0f)
+#define PAL_POSINF -logf(0.0f)
+#define PAL_NEGINF logf(0.0f)
+
+/**
+ * Helper test structure
+ */
+struct test
+{
+ float x; /* first component of the value to test the function with */
+ float y; /* second component of the value to test the function with */
+ float expected; /* expected result */
+ float variance; /* maximum delta between the expected and actual result */
+};
+
+/**
+ * validate
+ *
+ * test validation function
+ */
+void __cdecl validate(float x, float y, float expected, float variance)
+{
+ float result = powf(x, y);
+
+ /*
+ * The test is valid when the difference between result
+ * and expected is less than or equal to variance
+ */
+ float delta = fabsf(result - expected);
+
+ if (delta > variance)
+ {
+ Fail("powf(%g, %g) returned %10.9g when it should have returned %10.9g",
+ x, y, result, expected);
+ }
+}
+
+/**
+ * validate
+ *
+ * test validation function for values returning NaN
+ */
+void __cdecl validate_isnan(float x, float y)
+{
+ float result = powf(x, y);
+
+ if (!_isnanf(result))
+ {
+ Fail("powf(%g, %g) returned %10.9g when it should have returned %10.9g",
+ x, y, result, PAL_NAN);
+ }
+}
+
+/**
+ * main
+ *
+ * executable entry point
+ */
+int __cdecl main(int argc, char **argv)
+{
+ struct test tests[] =
+ {
+ /* x y expected variance */
+ { PAL_NEGINF, PAL_NEGINF, 0, PAL_EPSILON },
+ { PAL_NEGINF, PAL_POSINF, PAL_POSINF, 0 },
+
+ { -10, PAL_NEGINF, 0, PAL_EPSILON },
+ { -10, -1, -0.1f, PAL_EPSILON },
+ { -10, 0, 1, PAL_EPSILON * 10 },
+ { -10, 1, -10, PAL_EPSILON * 100 },
+ { -10, PAL_POSINF, PAL_POSINF, 0 },
+
+ { -2.71828183f, PAL_NEGINF, 0, PAL_EPSILON }, // x: -(e)
+ { -2.71828183f, -1, -0.367879441f, PAL_EPSILON }, // x: -(e)
+ { -2.71828183f, 0, 1, PAL_EPSILON * 10 }, // x: -(e)
+ { -2.71828183f, 1, -2.71828183f, PAL_EPSILON * 10 }, // x: -(e) expected: e
+ { -2.71828183f, PAL_POSINF, PAL_POSINF, 0 }, // x: -(e)
+
+ { -0.0, PAL_NEGINF, PAL_POSINF, 0 },
+ { -0.0, -1, PAL_NEGINF, 0 },
+ { -0.0f, -0.0f, 1, PAL_EPSILON * 10 },
+ { -0.0f, 0, 1, PAL_EPSILON * 10 },
+ { -0.0, 1, -0.0, PAL_EPSILON },
+ { -0.0, PAL_POSINF, 0, PAL_EPSILON },
+
+ { 0.0, PAL_NEGINF, PAL_POSINF, 0 },
+ { 0.0, -1, PAL_POSINF, 0 },
+ { 0, -0.0f, 1, PAL_EPSILON * 10 },
+ { 0, 0, 1, PAL_EPSILON * 10 },
+ { 0.0, 1, 0, PAL_EPSILON },
+ { 0.0, PAL_POSINF, 0, PAL_EPSILON },
+
+ { 1, PAL_NEGINF, 1, PAL_EPSILON * 10 },
+ { 1, PAL_POSINF, 1, PAL_EPSILON * 10 },
+
+ { 2.71828183f, PAL_NEGINF, 0, PAL_EPSILON },
+ { 2.71828183f, -3.14159265f, 0.0432139183f, PAL_EPSILON / 10 }, // x: e y: -(pi)
+ { 2.71828183f, -2.71828183f, 0.0659880358f, PAL_EPSILON / 10 }, // x: e y: -(e)
+ { 2.71828183f, -2.30258509f, 0.1f, PAL_EPSILON }, // x: e y: -(ln(10))
+ { 2.71828183f, -1.57079633f, 0.207879576f, PAL_EPSILON }, // x: e y: -(pi / 2)
+ { 2.71828183f, -1.44269504f, 0.236290088f, PAL_EPSILON }, // x: e y: -(logf2(e))
+ { 2.71828183f, -1.41421356f, 0.243116734f, PAL_EPSILON }, // x: e y: -(sqrtf(2))
+ { 2.71828183f, -1.12837917f, 0.323557264f, PAL_EPSILON }, // x: e y: -(2 / sqrtf(pi))
+ { 2.71828183f, -1, 0.367879441f, PAL_EPSILON }, // x: e y: -(1)
+ { 2.71828183f, -0.785398163f, 0.455938128f, PAL_EPSILON }, // x: e y: -(pi / 4)
+ { 2.71828183f, -0.707106781f, 0.493068691f, PAL_EPSILON }, // x: e y: -(1 / sqrtf(2))
+ { 2.71828183f, -0.693147181f, 0.5f, PAL_EPSILON }, // x: e y: -(ln(2))
+ { 2.71828183f, -0.636619772f, 0.529077808f, PAL_EPSILON }, // x: e y: -(2 / pi)
+ { 2.71828183f, -0.434294482f, 0.647721485f, PAL_EPSILON }, // x: e y: -(log10f(e))
+ { 2.71828183f, -0.318309886f, 0.727377349f, PAL_EPSILON }, // x: e y: -(1 / pi)
+ { 2.71828183f, 0, 1, PAL_EPSILON * 10 }, // x: e
+ { 2.71828183f, 0.318309886f, 1.37480223f, PAL_EPSILON * 10 }, // x: e y: 1 / pi
+ { 2.71828183f, 0.434294482f, 1.54387344f, PAL_EPSILON * 10 }, // x: e y: log10f(e)
+ { 2.71828183f, 0.636619772f, 1.89008116f, PAL_EPSILON * 10 }, // x: e y: 2 / pi
+ { 2.71828183f, 0.693147181f, 2, PAL_EPSILON * 10 }, // x: e y: ln(2)
+ { 2.71828183f, 0.707106781f, 2.02811498f, PAL_EPSILON * 10 }, // x: e y: 1 / sqrtf(2)
+ { 2.71828183f, 0.785398163f, 2.19328005f, PAL_EPSILON * 10 }, // x: e y: pi / 4
+ { 2.71828183f, 1, 2.71828183f, PAL_EPSILON * 10 }, // x: e expected: e
+ { 2.71828183f, 1.12837917f, 3.09064302f, PAL_EPSILON * 10 }, // x: e y: 2 / sqrtf(pi)
+ { 2.71828183f, 1.41421356f, 4.11325038f, PAL_EPSILON * 10 }, // x: e y: sqrtf(2)
+ { 2.71828183f, 1.44269504f, 4.23208611f, PAL_EPSILON * 10 }, // x: e y: logf2(e)
+ { 2.71828183f, 1.57079633f, 4.81047738f, PAL_EPSILON * 10 }, // x: e y: pi / 2
+ { 2.71828183f, 2.30258509f, 10, PAL_EPSILON * 100 }, // x: e y: ln(10)
+ { 2.71828183f, 2.71828183f, 15.1542622f, PAL_EPSILON * 100 }, // x: e y: e
+ { 2.71828183f, 3.14159265f, 23.1406926f, PAL_EPSILON * 100 }, // x: e y: pi
+ { 2.71828183f, PAL_POSINF, PAL_POSINF, 0 }, // x: e
+
+ { 10, PAL_NEGINF, 0, 0 },
+ { 10, -3.14159265f, 0.000721784159f, PAL_EPSILON / 1000 }, // y: -(pi)
+ { 10, -2.71828183f, 0.00191301410f, PAL_EPSILON / 100 }, // y: -(e)
+ { 10, -2.30258509f, 0.00498212830f, PAL_EPSILON / 100 }, // y: -(ln(10))
+ { 10, -1.57079633f, 0.0268660410f, PAL_EPSILON / 10 }, // y: -(pi / 2)
+ { 10, -1.44269504f, 0.0360831928f, PAL_EPSILON / 10 }, // y: -(logf2(e))
+ { 10, -1.41421356f, 0.0385288847f, PAL_EPSILON / 10 }, // y: -(sqrtf(2))
+ { 10, -1.12837917f, 0.0744082059f, PAL_EPSILON / 10 }, // y: -(2 / sqrtf(pi))
+ { 10, -1, 0.1f, PAL_EPSILON }, // y: -(1)
+ { 10, -0.785398163f, 0.163908636f, PAL_EPSILON }, // y: -(pi / 4)
+ { 10, -0.707106781f, 0.196287760f, PAL_EPSILON }, // y: -(1 / sqrtf(2))
+ { 10, -0.693147181f, 0.202699566f, PAL_EPSILON }, // y: -(ln(2))
+ { 10, -0.636619772f, 0.230876765f, PAL_EPSILON }, // y: -(2 / pi)
+ { 10, -0.434294482f, 0.367879441f, PAL_EPSILON }, // y: -(log10f(e))
+ { 10, -0.318309886f, 0.480496373f, PAL_EPSILON }, // y: -(1 / pi)
+ { 10, 0, 1, PAL_EPSILON * 10 },
+ { 10, 0.318309886f, 2.08118116f, PAL_EPSILON * 10 }, // y: 1 / pi
+ { 10, 0.434294482f, 2.71828183f, PAL_EPSILON * 10 }, // y: log10f(e) expected: e
+ { 10, 0.636619772f, 4.33131503f, PAL_EPSILON * 10 }, // y: 2 / pi
+ { 10, 0.693147181f, 4.93340967f, PAL_EPSILON * 10 }, // y: ln(2)
+ { 10, 0.707106781f, 5.09456117f, PAL_EPSILON * 10 }, // y: 1 / sqrtf(2)
+ { 10, 0.785398163f, 6.10095980f, PAL_EPSILON * 10 }, // y: pi / 4
+ { 10, 1, 10, PAL_EPSILON * 100 },
+ { 10, 1.12837917f, 13.4393779f, PAL_EPSILON * 100 }, // y: 2 / sqrtf(pi)
+ { 10, 1.41421356f, 25.9545535f, PAL_EPSILON * 100 }, // y: sqrtf(2)
+ { 10, 1.44269504f, 27.7137338f, PAL_EPSILON * 100 }, // y: logf2(e)
+ { 10, 1.57079633f, 37.2217105f, PAL_EPSILON * 100 }, // y: pi / 2
+ { 10, 2.30258509f, 200.717432f, PAL_EPSILON * 1000 }, // y: ln(10)
+ { 10, 2.71828183f, 522.735300f, PAL_EPSILON * 1000 }, // y: e
+ { 10, 3.14159265f, 1385.45573f, PAL_EPSILON * 10000 }, // y: pi
+ { 10, PAL_POSINF, PAL_POSINF, 0 },
+
+ { PAL_POSINF, PAL_NEGINF, 0, PAL_EPSILON },
+ { PAL_POSINF, PAL_POSINF, PAL_POSINF, 0 },
+ };
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+ for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++)
+ {
+ validate(tests[i].x, tests[i].y, tests[i].expected, tests[i].variance);
+ }
+
+ validate_isnan(-10, -1.57079633f); // y: -(pi / 2)
+ validate_isnan(-10, -0.785398163f); // y: -(pi / 4)
+ validate_isnan(-10, 0.785398163f); // y: pi / 4
+ validate_isnan(-10, 1.57079633f); // y: pi / 2
+
+ validate_isnan(-2.71828183f, -1.57079633f); // x: -(e) y: -(pi / 2)
+ validate_isnan(-2.71828183f, -0.785398163f); // x: -(e) y: -(pi / 4)
+ validate_isnan(-2.71828183f, 0.785398163f); // x: -(e) y: pi / 4
+ validate_isnan(-2.71828183f, 1.57079633f); // x: -(e) y: pi / 2
+
+ validate_isnan(-1, PAL_NEGINF);
+ validate_isnan(-1, PAL_POSINF);
+
+ validate_isnan(PAL_NAN, -0.0);
+ validate_isnan(PAL_NAN, 0);
+
+ validate_isnan(PAL_NEGINF, PAL_NAN);
+ validate_isnan(PAL_NAN, PAL_NEGINF);
+
+ validate_isnan(PAL_POSINF, PAL_NAN);
+ validate_isnan(PAL_NAN, PAL_POSINF);
+
+ validate_isnan(PAL_NAN, PAL_NAN);
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/powf/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/powf/test1/testinfo.dat
new file mode 100644
index 0000000000..778c042025
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/powf/test1/testinfo.dat
@@ -0,0 +1,17 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = powf
+Name = Call powf with some std input/output.
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Call the powf function with various num/expfonent pairs
+= that should produce std answers.
+
+
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/sinf/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sinf/CMakeLists.txt
new file mode 100644
index 0000000000..5e1ef7f28b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sinf/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
diff --git a/src/pal/tests/palsuite/c_runtime/sinf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sinf/test1/CMakeLists.txt
new file mode 100644
index 0000000000..0651b43d1d
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sinf/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_sinf_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_sinf_test1 coreclrpal)
+
+target_link_libraries(paltest_sinf_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/sinf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/sinf/test1/test1.c
new file mode 100644
index 0000000000..d5bd248935
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sinf/test1/test1.c
@@ -0,0 +1,130 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Test to ensure that sinf return the correct values
+**
+** Dependencies: PAL_Initialize
+** PAL_Terminate
+** Fail
+** fabs
+**
+**===========================================================================*/
+
+#include <palsuite.h>
+
+// binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this
+// is slightly too accurate when writing tests meant to run against libm implementations
+// for various platforms. 2^-21 (approx. 4.76e-07) seems to be as accurate as we can get.
+//
+// The tests themselves will take PAL_EPSILON and adjust it according to the expected result
+// so that the delta used for comparison will compare the most significant digits and ignore
+// any digits that are outside the double precision range (6-9 digits).
+
+// For example, a test with an expect result in the format of 0.xxxxxxxxx will use PAL_EPSILON
+// for the variance, while an expected result in the format of 0.0xxxxxxxxx will use
+// PAL_EPSILON / 10 and and expected result in the format of x.xxxxxx will use PAL_EPSILON * 10.
+#define PAL_EPSILON 4.76837158e-07
+
+#define PAL_NAN sqrtf(-1.0f)
+#define PAL_POSINF -logf(0.0f)
+#define PAL_NEGINF logf(0.0f)
+
+/**
+ * Helper test structure
+ */
+struct test
+{
+ float value; /* value to test the function with */
+ float expected; /* expected result */
+ float variance; /* maximum delta between the expected and actual result */
+};
+
+/**
+ * validate
+ *
+ * test validation function
+ */
+void __cdecl validate(float value, float expected, float variance)
+{
+ float result = sinf(value);
+
+ /*
+ * The test is valid when the difference between result
+ * and expected is less than or equal to variance
+ */
+ float delta = fabsf(result - expected);
+
+ if (delta > variance)
+ {
+ Fail("sinf(%g) returned %10.9g when it should have returned %10.9g",
+ value, result, expected);
+ }
+}
+
+/**
+ * validate
+ *
+ * test validation function for values returning NaN
+ */
+void __cdecl validate_isnan(float value)
+{
+ float result = sinf(value);
+
+ if (!_isnanf(result))
+ {
+ Fail("sinf(%g) returned %10.9g when it should have returned %10.9g",
+ value, result, PAL_NAN);
+ }
+}
+
+/**
+ * main
+ *
+ * executable entry point
+ */
+int __cdecl main(int argc, char **argv)
+{
+ struct test tests[] =
+ {
+ /* value expected variance */
+ { 0, 0, PAL_EPSILON },
+ { 0.318309886f, 0.312961796f, PAL_EPSILON }, // value: 1 / pi
+ { 0.434294482f, 0.420770483f, PAL_EPSILON }, // value: log10f(e)
+ { 0.636619772f, 0.594480769f, PAL_EPSILON }, // value: 2 / pi
+ { 0.693147181f, 0.638961276f, PAL_EPSILON }, // value: ln(2)
+ { 0.707106781f, 0.649636939f, PAL_EPSILON }, // value: 1 / sqrtf(2)
+ { 0.785398163f, 0.707106781f, PAL_EPSILON }, // value: pi / 4, expected: 1 / sqrtf(2)
+ { 1, 0.841470985f, PAL_EPSILON },
+ { 1.12837917f, 0.903719457f, PAL_EPSILON }, // value: 2 / sqrtf(pi)
+ { 1.41421356f, 0.987765946f, PAL_EPSILON }, // value: sqrtf(2)
+ { 1.44269504f, 0.991806244f, PAL_EPSILON }, // value: logf2(e)
+ { 1.57079633f, 1, PAL_EPSILON * 10 }, // value: pi / 2
+ { 2.30258509f, 0.743980337f, PAL_EPSILON }, // value: ln(10)
+ { 2.71828183f, 0.410781291f, PAL_EPSILON }, // value: e
+ { 3.14159265f, 0, PAL_EPSILON }, // value: pi
+ };
+
+ /* PAL initialization */
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+ for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++)
+ {
+ validate( tests[i].value, tests[i].expected, tests[i].variance);
+ validate(-tests[i].value, -tests[i].expected, tests[i].variance);
+ }
+
+ validate_isnan(PAL_NEGINF);
+ validate_isnan(PAL_NAN);
+ validate_isnan(PAL_POSINF);
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/sinf/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sinf/test1/testinfo.dat
new file mode 100644
index 0000000000..08ff6026cb
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sinf/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = sinf
+Name = Positive Test for sinf
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Passes to sinf() a series of angle value, checking that
+= each one return to correct value.
diff --git a/src/pal/tests/palsuite/c_runtime/sinhf/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sinhf/CMakeLists.txt
new file mode 100644
index 0000000000..5e1ef7f28b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sinhf/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
diff --git a/src/pal/tests/palsuite/c_runtime/sinhf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sinhf/test1/CMakeLists.txt
new file mode 100644
index 0000000000..72cce43460
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sinhf/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_sinhf_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_sinhf_test1 coreclrpal)
+
+target_link_libraries(paltest_sinhf_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/sinhf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/sinhf/test1/test1.c
new file mode 100644
index 0000000000..4e706a2f71
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sinhf/test1/test1.c
@@ -0,0 +1,129 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Test to ensure that sinhf return the correct values
+**
+** Dependencies: PAL_Initialize
+** PAL_Terminate
+** Fail
+** fabs
+**
+**===========================================================================*/
+
+#include <palsuite.h>
+
+// binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this
+// is slightly too accurate when writing tests meant to run against libm implementations
+// for various platforms. 2^-21 (approx. 4.76e-07) seems to be as accurate as we can get.
+//
+// The tests themselves will take PAL_EPSILON and adjust it according to the expected result
+// so that the delta used for comparison will compare the most significant digits and ignore
+// any digits that are outside the double precision range (6-9 digits).
+
+// For example, a test with an expect result in the format of 0.xxxxxxxxx will use PAL_EPSILON
+// for the variance, while an expected result in the format of 0.0xxxxxxxxx will use
+// PAL_EPSILON / 10 and and expected result in the format of x.xxxxxx will use PAL_EPSILON * 10.
+#define PAL_EPSILON 4.76837158e-07
+
+#define PAL_NAN sqrtf(-1.0f)
+#define PAL_POSINF -logf(0.0f)
+#define PAL_NEGINF logf(0.0f)
+
+/**
+ * Helper test structure
+ */
+struct test
+{
+ float value; /* value to test the function with */
+ float expected; /* expected result */
+ float variance; /* maximum delta between the expected and actual result */
+};
+
+/**
+ * validate
+ *
+ * test validation function
+ */
+void __cdecl validate(float value, float expected, float variance)
+{
+ float result = sinhf(value);
+
+ /*
+ * The test is valid when the difference between result
+ * and expected is less than or equal to variance
+ */
+ float delta = fabsf(result - expected);
+
+ if (delta > variance)
+ {
+ Fail("sinhf(%g) returned %10.9g when it should have returned %10.9g",
+ value, result, expected);
+ }
+}
+
+/**
+ * validate
+ *
+ * test validation function for values returning NaN
+ */
+void __cdecl validate_isnan(float value)
+{
+ float result = sinhf(value);
+
+ if (!_isnanf(result))
+ {
+ Fail("sinhf(%g) returned %10.9g when it should have returned %10.9g",
+ value, result, PAL_NAN);
+ }
+}
+
+/**
+ * main
+ *
+ * executable entry point
+ */
+int __cdecl main(int argc, char **argv)
+{
+ struct test tests[] =
+ {
+ /* value expected variance */
+ { 0, 0, PAL_EPSILON },
+ { 0.318309886f, 0.323712439f, PAL_EPSILON }, // value: 1 / pi
+ { 0.434294482f, 0.448075979f, PAL_EPSILON }, // value: log10f(e)
+ { 0.636619772f, 0.680501678f, PAL_EPSILON }, // value: 2 / pi
+ { 0.693147181f, 0.75, PAL_EPSILON }, // value: ln(2)
+ { 0.707106781f, 0.767523145f, PAL_EPSILON }, // value: 1 / sqrtf(2)
+ { 0.785398163f, 0.868670961f, PAL_EPSILON }, // value: pi / 4
+ { 1, 1.17520119f, PAL_EPSILON * 10 },
+ { 1.12837917f, 1.38354288f, PAL_EPSILON * 10 }, // value: 2 / sqrtf(pi)
+ { 1.41421356f, 1.93506682f, PAL_EPSILON * 10 }, // value: sqrtf(2)
+ { 1.44269504f, 1.99789801f, PAL_EPSILON * 10 }, // value: logf2(e)
+ { 1.57079633f, 2.30129890f, PAL_EPSILON * 10 }, // value: pi / 2
+ { 2.30258509f, 4.95f, PAL_EPSILON * 10 }, // value: ln(10)
+ { 2.71828183f, 7.54413710f, PAL_EPSILON * 10 }, // value: e
+ { 3.14159265f, 11.5487394f, PAL_EPSILON * 100 }, // value: pi
+ { PAL_POSINF, PAL_POSINF, 0 },
+ };
+
+ /* PAL initialization */
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+ for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++)
+ {
+ validate( tests[i].value, tests[i].expected, tests[i].variance);
+ validate(-tests[i].value, -tests[i].expected, tests[i].variance);
+ }
+
+ validate_isnan(PAL_NAN);
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/sinhf/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sinhf/test1/testinfo.dat
new file mode 100644
index 0000000000..cfb27f5427
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sinhf/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = sinhf
+Name = Positive Test for sinhf
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Passes to sinhf() a series of angle value, checking that
+= each one return to correct value.
diff --git a/src/pal/tests/palsuite/c_runtime/sqrtf/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sqrtf/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sqrtf/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/sqrtf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sqrtf/test1/CMakeLists.txt
new file mode 100644
index 0000000000..96b6ffa998
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sqrtf/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_sqrtf_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_sqrtf_test1 coreclrpal)
+
+target_link_libraries(paltest_sqrtf_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/sqrtf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/sqrtf/test1/test1.c
new file mode 100644
index 0000000000..cb1ac9e7df
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sqrtf/test1/test1.c
@@ -0,0 +1,122 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test1.c
+**
+** Purpose: Call the sqrtf function on a positive value, a positive value
+** with a decimal and on the maxium possible float value.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+// binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this
+// is slightly too accurate when writing tests meant to run against libm implementations
+// for various platforms. 2^-21 (approx. 4.76e-07) seems to be as accurate as we can get.
+//
+// The tests themselves will take PAL_EPSILON and adjust it according to the expected result
+// so that the delta used for comparison will compare the most significant digits and ignore
+// any digits that are outside the double precision range (6-9 digits).
+
+// For example, a test with an expect result in the format of 0.xxxxxxxxx will use PAL_EPSILON
+// for the variance, while an expected result in the format of 0.0xxxxxxxxx will use
+// PAL_EPSILON / 10 and and expected result in the format of x.xxxxxx will use PAL_EPSILON * 10.
+#define PAL_EPSILON 4.76837158e-07
+
+#define PAL_NAN sqrtf(-1.0f)
+#define PAL_POSINF -logf(0.0f)
+#define PAL_NEGINF logf(0.0f)
+
+/**
+ * Helper test structure
+ */
+struct test
+{
+ float value; /* value to test the function with */
+ float expected; /* expected result */
+ float variance; /* maximum delta between the expected and actual result */
+};
+
+/**
+ * validate
+ *
+ * test validation function
+ */
+void __cdecl validate(float value, float expected, float variance)
+{
+ float result = sqrtf(value);
+
+ /*
+ * The test is valid when the difference between result
+ * and expected is less than or equal to variance
+ */
+ float delta = fabsf(result - expected);
+
+ if (delta > variance)
+ {
+ Fail("sqrtf(%g) returned %10.9g when it should have returned %10.9g",
+ value, result, expected);
+ }
+}
+
+/**
+ * validate
+ *
+ * test validation function for values returning NaN
+ */
+void __cdecl validate_isnan(float value)
+{
+ float result = sqrtf(value);
+
+ if (!_isnanf(result))
+ {
+ Fail("sqrtf(%g) returned %10.9g when it should have returned %10.9g",
+ value, result, PAL_NAN);
+ }
+}
+
+int __cdecl main(int argc, char **argv)
+{
+ struct test tests[] =
+ {
+ /* value expected variance */
+ { 0.318309886f, 0.564189584f, PAL_EPSILON }, // value: 1 / pi
+ { 0.434294482f, 0.659010229f, PAL_EPSILON }, // value: log10f(e)
+ { 0.636619772f, 0.797884561f, PAL_EPSILON }, // value: 2 / pi
+ { 0.693147181f, 0.832554611f, PAL_EPSILON }, // value: ln(2)
+ { 0.707106781f, 0.840896415f, PAL_EPSILON }, // value: 1 / sqrtf(2)
+ { 0.785398163f, 0.886226925f, PAL_EPSILON }, // value: pi / 4
+ { 1, 1, PAL_EPSILON * 10 },
+ { 1.12837917f, 1.06225193f, PAL_EPSILON * 10 }, // value: 2 / sqrtf(pi)
+ { 1.41421356f, 1.18920712f, PAL_EPSILON * 10 }, // value: sqrtf(2)
+ { 1.44269504f, 1.20112241f, PAL_EPSILON * 10 }, // value: logf2(e)
+ { 1.57079633f, 1.25331414f, PAL_EPSILON * 10 }, // value: pi / 2
+ { 2.30258509f, 1.51742713f, PAL_EPSILON * 10 }, // value: ln(10)
+ { 2.71828183f, 1.64872127f, PAL_EPSILON * 10 }, // value: e
+ { 3.14159265f, 1.77245385F, PAL_EPSILON * 10 }, // value: pi
+ };
+
+ /* PAL initialization */
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+ validate(-0.0f, -0.0f, PAL_EPSILON);
+ validate( 0.0f, 0.0f, PAL_EPSILON);
+
+ for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++)
+ {
+ validate(tests[i].value, tests[i].expected, tests[i].variance);
+ validate_isnan(-tests[i].value);
+ }
+
+ validate_isnan(PAL_NAN);
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/sqrtf/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sqrtf/test1/testinfo.dat
new file mode 100644
index 0000000000..00d8ab2e43
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sqrtf/test1/testinfo.dat
@@ -0,0 +1,17 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = sqrtf
+Name = Call sqrtf on positive values and zero.
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Call the sqrtf function on a positive value, a positive value
+= with a decimal and on the maxium possible float value.
+
+
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/tanf/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/tanf/CMakeLists.txt
new file mode 100644
index 0000000000..5e1ef7f28b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/tanf/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
diff --git a/src/pal/tests/palsuite/c_runtime/tanf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/tanf/test1/CMakeLists.txt
new file mode 100644
index 0000000000..cd588ea23e
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/tanf/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_tanf_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_tanf_test1 coreclrpal)
+
+target_link_libraries(paltest_tanf_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/tanf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/tanf/test1/test1.c
new file mode 100644
index 0000000000..18d5c4e59d
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/tanf/test1/test1.c
@@ -0,0 +1,136 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Test to ensure that tanf return the correct values
+**
+** Dependencies: PAL_Initialize
+** PAL_Terminate
+** Fail
+** fabs
+**
+**===========================================================================*/
+
+#include <palsuite.h>
+
+// binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this
+// is slightly too accurate when writing tests meant to run against libm implementations
+// for various platforms. 2^-21 (approx. 4.76e-07) seems to be as accurate as we can get.
+//
+// The tests themselves will take PAL_EPSILON and adjust it according to the expected result
+// so that the delta used for comparison will compare the most significant digits and ignore
+// any digits that are outside the double precision range (6-9 digits).
+
+// For example, a test with an expect result in the format of 0.xxxxxxxxx will use PAL_EPSILON
+// for the variance, while an expected result in the format of 0.0xxxxxxxxx will use
+// PAL_EPSILON / 10 and and expected result in the format of x.xxxxxx will use PAL_EPSILON * 10.
+#define PAL_EPSILON 4.76837158e-07
+
+#define PAL_NAN sqrtf(-1.0f)
+#define PAL_POSINF -logf(0.0f)
+#define PAL_NEGINF logf(0.0f)
+
+/**
+ * Helper test structure
+ */
+struct test
+{
+ float value; /* value to test the function with */
+ float expected; /* expected result */
+ float variance; /* maximum delta between the expected and actual result */
+};
+
+/**
+ * validate
+ *
+ * test validation function
+ */
+void __cdecl validate(float value, float expected, float variance)
+{
+ float result = tanf(value);
+
+ /*
+ * The test is valid when the difference between result
+ * and expected is less than or equal to variance
+ */
+ float delta = fabsf(result - expected);
+
+ if (delta > variance)
+ {
+ Fail("tanf(%g) returned %10.9g when it should have returned %10.9g",
+ value, result, expected);
+ }
+}
+
+/**
+ * validate
+ *
+ * test validation function for values returning NaN
+ */
+void __cdecl validate_isnan(float value)
+{
+ float result = tanf(value);
+
+ if (!_isnanf(result))
+ {
+ Fail("tanf(%g) returned %10.9g when it should have returned %10.9g",
+ value, result, PAL_NAN);
+ }
+}
+
+/**
+ * main
+ *
+ * executable entry point
+ */
+int __cdecl main(int argc, char **argv)
+{
+ struct test tests[] =
+ {
+ /* value expected variance */
+ { 0, 0, PAL_EPSILON },
+ { 0.318309886f, 0.329514733f, PAL_EPSILON }, // value: 1 / pi
+ { 0.434294482f, 0.463829067f, PAL_EPSILON }, // value: log10f(e)
+ { 0.636619772f, 0.739302950f, PAL_EPSILON }, // value: 2 / pi
+ { 0.693147181f, 0.830640878f, PAL_EPSILON }, // value: ln(2)
+ { 0.707106781f, 0.854510432f, PAL_EPSILON }, // value: 1 / sqrtf(2)
+ { 0.785398163f, 1, PAL_EPSILON * 10 }, // value: pi / 4
+ { 1, 1.55740772f, PAL_EPSILON * 10 },
+ { 1.12837917f, 2.11087684f, PAL_EPSILON * 10 }, // value: 2 / sqrtf(pi)
+ { 1.41421356f, 6.33411917f, PAL_EPSILON * 10 }, // value: sqrtf(2)
+ { 1.44269504f, 7.76357567f, PAL_EPSILON * 10 }, // value: logf2(e)
+ // SEE BELOW -- { 1.57079633f, PAL_POSINF, 0 }, // value: pi / 2
+ { 2.30258509f, -1.11340715f, PAL_EPSILON * 10 }, // value: ln(10)
+ { 2.71828183f, -0.450549534f, PAL_EPSILON }, // value: e
+ { 3.14159265f, 0, PAL_EPSILON }, // value: pi
+ };
+
+ /* PAL initialization */
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+ for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++)
+ {
+ validate( tests[i].value, tests[i].expected, tests[i].variance);
+ validate(-tests[i].value, -tests[i].expected, tests[i].variance);
+ }
+
+ // -- SPECIAL CASE --
+ // Normally, tanf(pi / 2) would return PAL_POSINF (atan2f(PAL_POSINF) does return (pi / 2)).
+ // However, it seems instead (on all supported systems), we get a different number entirely.
+ validate( 1.57079633f, -22877332.0, PAL_EPSILON * 100000000);
+ validate(-1.57079633f, 22877332.0, PAL_EPSILON * 100000000);
+
+ validate_isnan(PAL_NEGINF);
+ validate_isnan(PAL_NAN);
+ validate_isnan(PAL_POSINF);
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/tanf/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/tanf/test1/testinfo.dat
new file mode 100644
index 0000000000..aa33232adc
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/tanf/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = tanf
+Name = Positive Test for tanf
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Passes to tanf() a series of angle value, checking that
+= each one return to correct value.
diff --git a/src/pal/tests/palsuite/c_runtime/tanhf/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/tanhf/CMakeLists.txt
new file mode 100644
index 0000000000..5e1ef7f28b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/tanhf/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
diff --git a/src/pal/tests/palsuite/c_runtime/tanhf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/tanhf/test1/CMakeLists.txt
new file mode 100644
index 0000000000..fd0af2a46f
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/tanhf/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_tanhf_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_tanhf_test1 coreclrpal)
+
+target_link_libraries(paltest_tanhf_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/tanhf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/tanhf/test1/test1.c
new file mode 100644
index 0000000000..904729a2c4
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/tanhf/test1/test1.c
@@ -0,0 +1,129 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Test to ensure that tanhf return the correct values
+**
+** Dependencies: PAL_Initialize
+** PAL_Terminate
+** Fail
+** fabs
+**
+**===========================================================================*/
+
+#include <palsuite.h>
+
+// binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this
+// is slightly too accurate when writing tests meant to run against libm implementations
+// for various platforms. 2^-21 (approx. 4.76e-07) seems to be as accurate as we can get.
+//
+// The tests themselves will take PAL_EPSILON and adjust it according to the expected result
+// so that the delta used for comparison will compare the most significant digits and ignore
+// any digits that are outside the double precision range (6-9 digits).
+
+// For example, a test with an expect result in the format of 0.xxxxxxxxx will use PAL_EPSILON
+// for the variance, while an expected result in the format of 0.0xxxxxxxxx will use
+// PAL_EPSILON / 10 and and expected result in the format of x.xxxxxx will use PAL_EPSILON * 10.
+#define PAL_EPSILON 4.76837158e-07
+
+#define PAL_NAN sqrtf(-1.0f)
+#define PAL_POSINF -logf(0.0f)
+#define PAL_NEGINF logf(0.0f)
+
+/**
+ * Helper test structure
+ */
+struct test
+{
+ float value; /* value to test the function with */
+ float expected; /* expected result */
+ float variance; /* maximum delta between the expected and actual result */
+};
+
+/**
+ * validate
+ *
+ * test validation function
+ */
+void __cdecl validate(float value, float expected, float variance)
+{
+ float result = tanhf(value);
+
+ /*
+ * The test is valid when the difference between result
+ * and expected is less than or equal to variance
+ */
+ float delta = fabsf(result - expected);
+
+ if (delta > variance)
+ {
+ Fail("tanhf(%g) returned %10.9g when it should have returned %10.9g",
+ value, result, expected);
+ }
+}
+
+/**
+ * validate
+ *
+ * test validation function for values returning NaN
+ */
+void __cdecl validate_isnan(float value)
+{
+ float result = tanhf(value);
+
+ if (!_isnanf(result))
+ {
+ Fail("tanhf(%g) returned %10.9g when it should have returned %10.9g",
+ value, result, PAL_NAN);
+ }
+}
+
+/**
+ * main
+ *
+ * executable entry point
+ */
+int __cdecl main(int argc, char **argv)
+{
+ struct test tests[] =
+ {
+ /* value expected variance */
+ { 0, 0, PAL_EPSILON },
+ { 0.318309886f, 0.307977913f, PAL_EPSILON }, // value: 1 / pi
+ { 0.434294482f, 0.408904012f, PAL_EPSILON }, // value: log10f(e)
+ { 0.636619772f, 0.562593600f, PAL_EPSILON }, // value: 2 / pi
+ { 0.693147181f, 0.6f, PAL_EPSILON }, // value: ln(2)
+ { 0.707106781f, 0.608859365f, PAL_EPSILON }, // value: 1 / sqrtf(2)
+ { 0.785398163f, 0.655794203f, PAL_EPSILON }, // value: pi / 4
+ { 1, 0.761594156f, PAL_EPSILON },
+ { 1.12837917f, 0.810463806f, PAL_EPSILON }, // value: 2 / sqrtf(pi)
+ { 1.41421356f, 0.888385562f, PAL_EPSILON }, // value: sqrtf(2)
+ { 1.44269504f, 0.894238946f, PAL_EPSILON }, // value: logf2(e)
+ { 1.57079633f, 0.917152336f, PAL_EPSILON }, // value: pi / 2
+ { 2.30258509f, 0.980198020f, PAL_EPSILON }, // value: ln(10)
+ { 2.71828183f, 0.991328916f, PAL_EPSILON }, // value: e
+ { 3.14159265f, 0.996272076f, PAL_EPSILON }, // value: pi
+ { PAL_POSINF, 1, PAL_EPSILON * 10 }
+ };
+
+ /* PAL initialization */
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+ for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++)
+ {
+ validate( tests[i].value, tests[i].expected, tests[i].variance);
+ validate(-tests[i].value, -tests[i].expected, tests[i].variance);
+ }
+
+ validate_isnan(PAL_NAN);
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/tanhf/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/tanhf/test1/testinfo.dat
new file mode 100644
index 0000000000..6c7594fc5a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/tanhf/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = tanhf
+Name = Positive Test for tanhf
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Passes to tanhf() a series of angle value, checking that
+= each one return to correct value.
diff --git a/src/pal/tests/palsuite/paltestlist.txt b/src/pal/tests/palsuite/paltestlist.txt
index d0a76e9573..24d2d9175f 100644
--- a/src/pal/tests/palsuite/paltestlist.txt
+++ b/src/pal/tests/palsuite/paltestlist.txt
@@ -1,20 +1,28 @@
c_runtime/abs/test1/paltest_abs_test1
c_runtime/acos/test1/paltest_acos_test1
+c_runtime/acosf/test1/paltest_acosf_test1
c_runtime/asin/test1/paltest_asin_test1
+c_runtime/asinf/test1/paltest_asinf_test1
c_runtime/atan/test1/paltest_atan_test1
c_runtime/atan2/test1/paltest_atan2_test1
+c_runtime/atan2f/test1/paltest_atan2f_test1
+c_runtime/atanf/test1/paltest_atanf_test1
c_runtime/atof/test1/paltest_atof_test1
c_runtime/atoi/test1/paltest_atoi_test1
c_runtime/atol/test1/paltest_atol_test1
c_runtime/bsearch/test1/paltest_bsearch_test1
c_runtime/bsearch/test2/paltest_bsearch_test2
c_runtime/ceil/test1/paltest_ceil_test1
+c_runtime/ceilf/test1/paltest_ceilf_test1
c_runtime/cos/test1/paltest_cos_test1
+c_runtime/cosf/test1/paltest_cosf_test1
c_runtime/cosh/test1/paltest_cosh_test1
+c_runtime/coshf/test1/paltest_coshf_test1
c_runtime/errno/test1/paltest_errno_test1
c_runtime/errno/test2/paltest_errno_test2
c_runtime/exit/test1/paltest_exit_test1
c_runtime/exp/test1/paltest_exp_test1
+c_runtime/expf/test1/paltest_expf_test1
c_runtime/fabs/test1/paltest_fabs_test1
c_runtime/fabsf/test1/paltest_fabsf_test1
c_runtime/fclose/test1/paltest_fclose_test1
@@ -24,6 +32,7 @@ c_runtime/fgets/test1/paltest_fgets_test1
c_runtime/fgets/test2/paltest_fgets_test2
c_runtime/fgets/test3/paltest_fgets_test3
c_runtime/floor/test1/paltest_floor_test1
+c_runtime/floorf/test1/paltest_floorf_test1
c_runtime/fmod/test1/paltest_fmod_test1
c_runtime/fmodf/test1/paltest_fmodf_test1
c_runtime/fopen/test1/paltest_fopen_test1
@@ -94,6 +103,8 @@ c_runtime/llabs/test1/paltest_llabs_test1
c_runtime/localtime/test1/paltest_localtime_test1
c_runtime/log/test1/paltest_log_test1
c_runtime/log10/test1/paltest_log10_test1
+c_runtime/log10f/test1/paltest_log10f_test1
+c_runtime/logf/test1/paltest_logf_test1
c_runtime/malloc/test1/paltest_malloc_test1
c_runtime/malloc/test2/paltest_malloc_test2
c_runtime/memchr/test1/paltest_memchr_test1
@@ -104,6 +115,7 @@ c_runtime/memset/test1/paltest_memset_test1
c_runtime/modf/test1/paltest_modf_test1
c_runtime/modff/test1/paltest_modff_test1
c_runtime/pow/test1/paltest_pow_test1
+c_runtime/powf/test1/paltest_powf_test1
c_runtime/printf/test1/paltest_printf_test1
c_runtime/printf/test10/paltest_printf_test10
c_runtime/printf/test11/paltest_printf_test11
@@ -128,7 +140,9 @@ c_runtime/qsort/test2/paltest_qsort_test2
c_runtime/rand_srand/test1/paltest_rand_srand_test1
c_runtime/realloc/test1/paltest_realloc_test1
c_runtime/sin/test1/paltest_sin_test1
+c_runtime/sinf/test1/paltest_sinf_test1
c_runtime/sinh/test1/paltest_sinh_test1
+c_runtime/sinhf/test1/paltest_sinhf_test1
c_runtime/sprintf/test1/paltest_sprintf_test1
c_runtime/sprintf/test10/paltest_sprintf_test10
c_runtime/sprintf/test11/paltest_sprintf_test11
@@ -149,6 +163,7 @@ c_runtime/sprintf/test7/paltest_sprintf_test7
c_runtime/sprintf/test8/paltest_sprintf_test8
c_runtime/sprintf/test9/paltest_sprintf_test9
c_runtime/sqrt/test1/paltest_sqrt_test1
+c_runtime/sqrtf/test1/paltest_sqrtf_test1
c_runtime/sscanf/test1/paltest_sscanf_test1
c_runtime/sscanf/test10/paltest_sscanf_test10
c_runtime/sscanf/test11/paltest_sscanf_test11
@@ -218,7 +233,9 @@ c_runtime/swscanf/test7/paltest_swscanf_test7
c_runtime/swscanf/test8/paltest_swscanf_test8
c_runtime/swscanf/test9/paltest_swscanf_test9
c_runtime/tan/test1/paltest_tan_test1
+c_runtime/tanf/test1/paltest_tanf_test1
c_runtime/tanh/test1/paltest_tanh_test1
+c_runtime/tanhf/test1/paltest_tanhf_test1
c_runtime/time/test1/paltest_time_test1
c_runtime/tolower/test1/paltest_tolower_test1
c_runtime/toupper/test1/paltest_toupper_test1
@@ -328,8 +345,10 @@ c_runtime/wprintf/test1/paltest_wprintf_test1
c_runtime/_alloca/test1/paltest_alloca_test1
c_runtime/_fdopen/test1/paltest_fdopen_test1
c_runtime/_finite/test1/paltest_finite_test1
+c_runtime/_finitef/test1/paltest_finitef_test1
c_runtime/_fullpath/test1/paltest_fullpath_test1
c_runtime/_isnan/test1/paltest_isnan_test1
+c_runtime/_isnanf/test1/paltest_isnanf_test1
c_runtime/_itow/test1/paltest_itow_test1
c_runtime/_makepath/test1/paltest_makepath_test1
c_runtime/_mbsdec/test1/paltest_mbsdec_test1
diff --git a/src/pal/tests/palsuite/palverify.dat b/src/pal/tests/palsuite/palverify.dat
index 36b48d66e8..dc30b86f08 100644
--- a/src/pal/tests/palsuite/palverify.dat
+++ b/src/pal/tests/palsuite/palverify.dat
@@ -7,11 +7,13 @@ c_runtime/_alloca/test1,1
c_runtime/_ecvt/test1,1
c_runtime/_fdopen/test1,1
c_runtime/_finite/test1,1
+c_runtime/_finitef/test1,1
c_runtime/_fullpath/test1,1
c_runtime/_gcvt/test1,1
c_runtime/_gcvt/test2,1
c_runtime/_getw/test1,1
c_runtime/_isnan/test1,1
+c_runtime/_isnanf/test1,1
c_runtime/_itow/test1,1
c_runtime/_makepath/test1,1
c_runtime/_mbsdec/test1,1
@@ -123,22 +125,30 @@ c_runtime/_wsplitpath/test1,1
c_runtime/_wtoi/test1,1
c_runtime/abs/test1,1
c_runtime/acos/test1,1
+c_runtime/acosf/test1,1
c_runtime/asin/test1,1
+c_runtime/asinf/test1,1
c_runtime/atan/test1,1
c_runtime/atan2/test1,1
+c_runtime/atan2f/test1,1
+c_runtime/atanf/test1,1
c_runtime/atof/test1,1
c_runtime/atoi/test1,1
c_runtime/atol/test1,1
c_runtime/bsearch/test1,1
c_runtime/bsearch/test2,1
c_runtime/ceil/test1,1
+c_runtime/ceilf/test1,1
c_runtime/cos/test1,1
+c_runtime/cosf/test1,1
c_runtime/cosh/test1,1
+c_runtime/coshf/test1,1
c_runtime/ctime/test1,1
c_runtime/errno/test1,1
c_runtime/errno/test2,1
c_runtime/exit/test1,1
c_runtime/exp/test1,1
+c_runtime/expf/test1,1
c_runtime/fabs/test1,1
c_runtime/fabsf/test1,1
c_runtime/fclose/test1,1
@@ -151,6 +161,7 @@ c_runtime/fgets/test1,1
c_runtime/fgets/test2,1
c_runtime/fgets/test3,1
c_runtime/floor/test1,1
+c_runtime/floorf/test1,1
c_runtime/fmod/test1,1
c_runtime/fmodf/test1,1
c_runtime/fopen/test1,1
@@ -230,6 +241,8 @@ c_runtime/llabs/test1,1
c_runtime/localtime/test1,1
c_runtime/log/test1,1
c_runtime/log10/test1,1
+c_runtime/log10f/test1,1
+c_runtime/logf/test1,1
c_runtime/malloc/test1,1
c_runtime/memchr/test1,1
c_runtime/memcmp/test1,1
@@ -238,6 +251,7 @@ c_runtime/memmove/test1,1
c_runtime/memset/test1,1
c_runtime/modf/test1,1
c_runtime/pow/test1,1
+c_runtime/powf/test1,1
c_runtime/printf/test1,1
c_runtime/printf/test2,1
c_runtime/printf/test3,1
@@ -262,7 +276,9 @@ c_runtime/qsort/test2,1
c_runtime/rand_srand/test1,1
c_runtime/realloc/test1,1
c_runtime/sin/test1,1
+c_runtime/sinf/test1,1
c_runtime/sinh/test1,1
+c_runtime/sinhf/test1,1
c_runtime/sprintf/test1,1
c_runtime/sprintf/test2,1
c_runtime/sprintf/test3,1
@@ -283,6 +299,7 @@ c_runtime/sprintf/test17,1
c_runtime/sprintf/test18,1
c_runtime/sprintf/test19,1
c_runtime/sqrt/test1,1
+c_runtime/sqrtf/test1,1
c_runtime/sscanf/test1,1
c_runtime/sscanf/test2,1
c_runtime/sscanf/test3,1
@@ -354,7 +371,9 @@ c_runtime/swscanf/test15,1
c_runtime/swscanf/test16,1
c_runtime/swscanf/test17,1
c_runtime/tan/test1,1
+c_runtime/tanf/test1,1
c_runtime/tanh/test1,1
+c_runtime/tanhf/test1,1
c_runtime/time/test1,1
c_runtime/tolower/test1,1
c_runtime/toupper/test1,1
diff --git a/src/vm/ecalllist.h b/src/vm/ecalllist.h
index d0c315dd58..2277b03470 100644
--- a/src/vm/ecalllist.h
+++ b/src/vm/ecalllist.h
@@ -1251,6 +1251,29 @@ FCFuncStart(gMathFuncs)
FCIntrinsic("Tanh", COMDouble::Tanh, CORINFO_INTRINSIC_Tanh)
FCFuncEnd()
+FCFuncStart(gMathFFuncs)
+ FCIntrinsic("Abs", COMSingle::Abs, CORINFO_INTRINSIC_Abs)
+ FCIntrinsic("Acos", COMSingle::Acos, CORINFO_INTRINSIC_Acos)
+ FCIntrinsic("Asin", COMSingle::Asin, CORINFO_INTRINSIC_Asin)
+ FCIntrinsic("Atan", COMSingle::Atan, CORINFO_INTRINSIC_Atan)
+ FCIntrinsic("Atan2", COMSingle::Atan2, CORINFO_INTRINSIC_Atan2)
+ FCIntrinsic("Ceiling", COMSingle::Ceil, CORINFO_INTRINSIC_Ceiling)
+ FCIntrinsic("Cos", COMSingle::Cos, CORINFO_INTRINSIC_Cos)
+ FCIntrinsic("Cosh", COMSingle::Cosh, CORINFO_INTRINSIC_Cosh)
+ FCIntrinsic("Exp", COMSingle::Exp, CORINFO_INTRINSIC_Exp)
+ FCIntrinsic("Floor", COMSingle::Floor, CORINFO_INTRINSIC_Floor)
+ FCFuncElement("Log", COMSingle::Log)
+ FCIntrinsic("Log10", COMSingle::Log10, CORINFO_INTRINSIC_Log10)
+ FCIntrinsic("Pow", COMSingle::Pow, CORINFO_INTRINSIC_Pow)
+ FCIntrinsic("Round", COMSingle::Round, CORINFO_INTRINSIC_Round)
+ FCIntrinsic("Sin", COMSingle::Sin, CORINFO_INTRINSIC_Sin)
+ FCIntrinsic("Sinh", COMSingle::Sinh, CORINFO_INTRINSIC_Sinh)
+ FCFuncElement("SplitFractionSingle", COMSingle::ModF)
+ FCIntrinsic("Sqrt", COMSingle::Sqrt, CORINFO_INTRINSIC_Sqrt)
+ FCIntrinsic("Tan", COMSingle::Tan, CORINFO_INTRINSIC_Tan)
+ FCIntrinsic("Tanh", COMSingle::Tanh, CORINFO_INTRINSIC_Tanh)
+FCFuncEnd()
+
FCFuncStart(gRuntimeThreadFuncs)
FCFuncElement("get_IsAlive", ThreadNative::IsAlive)
FCFuncElement("IsBackgroundNative", ThreadNative::IsBackground)
@@ -2252,6 +2275,7 @@ FCClassElement("Marshal", "System.Runtime.InteropServices", gInteropMarshalFuncs
FCClassElement("MarshalByRefObject", "System", gMarshalByRefFuncs)
#endif
FCClassElement("Math", "System", gMathFuncs)
+FCClassElement("MathF", "System", gMathFFuncs)
#ifdef MDA_SUPPORTED
FCClassElement("Mda", "System", gMda)
#endif