diff options
author | Tanner Gooding <tannergooding@users.noreply.github.com> | 2016-10-18 02:56:53 -0700 |
---|---|---|
committer | Jan Vorlicek <janvorli@microsoft.com> | 2016-10-18 11:56:53 +0200 |
commit | 6057b18d33216c3ee1436411e42e75a915a4714b (patch) | |
tree | 79f5282a27fbfb579763487a96c0e8f1bb56a9af | |
parent | bed314bb3005e3c5fc0b3c0723e398e702e08f65 (diff) | |
download | coreclr-6057b18d33216c3ee1436411e42e75a915a4714b.tar.gz coreclr-6057b18d33216c3ee1436411e42e75a915a4714b.tar.bz2 coreclr-6057b18d33216c3ee1436411e42e75a915a4714b.zip |
Adding single-precision math functions. (#5492)
* Adding single-precision math functions to floatsingle
* Adding single-precision math functions to the PAL layer.
* Adding single-precision math tests to the PAL layer.
* Adding single-precision math functions to mscorlib.
* Adding single-precision math function support to the vm.
* Updating floatsingle.cpp to define a _isnanf macro for Windows ARM.
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 |