diff options
author | Tanner Gooding <tagoo@outlook.com> | 2018-11-05 15:37:36 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-11-05 15:37:36 -0800 |
commit | 28417584d8e98ae7eac22e92b952778f8ea94047 (patch) | |
tree | a6010a24228ca769fc7a6381cbd04b3a762e9219 /src/pal | |
parent | d3a7c973723bf2610c7dcdcd00318c06a72a36f8 (diff) | |
download | coreclr-28417584d8e98ae7eac22e92b952778f8ea94047.tar.gz coreclr-28417584d8e98ae7eac22e92b952778f8ea94047.tar.bz2 coreclr-28417584d8e98ae7eac22e92b952778f8ea94047.zip |
Adding some new functions to System.Math and System.MathF (#20788)
* Adding BitIncrement, BitDecrement, CopySign, MaxMagnitude, and MinMagnitude to Math and MathF
* Adding FusedMultiplyAdd, IlogB, Log2, and ScaleB to Math and MathF
* Adding some basic PAL tests for fma, ilogb, log2, and scalbn
* Fixing a couple typos and adding clarifying comments
* Fixing the MSVC _VVV FCALL declarations
Diffstat (limited to 'src/pal')
35 files changed, 1532 insertions, 1 deletions
diff --git a/src/pal/inc/pal.h b/src/pal/inc/pal.h index 690804013e..a7f0ff5d74 100644 --- a/src/pal/inc/pal.h +++ b/src/pal/inc/pal.h @@ -4158,18 +4158,26 @@ SetThreadIdealProcessorEx( #define asinh PAL_asinh #define atan2 PAL_atan2 #define exp PAL_exp +#define fma PAL_fma +#define ilogb PAL_ilogb #define log PAL_log +#define log2 PAL_log2 #define log10 PAL_log10 #define pow PAL_pow +#define scalbn PAL_scalbn #define acosf PAL_acosf #define acoshf PAL_acoshf #define asinf PAL_asinf #define asinhf PAL_asinhf #define atan2f PAL_atan2f #define expf PAL_expf +#define fmaf PAL_fmaf +#define ilogbf PAL_ilogbf #define logf PAL_logf +#define log2f PAL_log2f #define log10f PAL_log10f #define powf PAL_powf +#define scalbnf PAL_scalbnf #define malloc PAL_malloc #define free PAL_free #define mkstemp PAL_mkstemp @@ -4424,10 +4432,14 @@ PALIMPORT double __cdecl exp(double); PALIMPORT double __cdecl fabs(double); PALIMPORT double __cdecl floor(double); PALIMPORT double __cdecl fmod(double, double); +PALIMPORT double __cdecl fma(double, double, double); +PALIMPORT int __cdecl ilogb(double); PALIMPORT double __cdecl log(double); +PALIMPORT double __cdecl log2(double); PALIMPORT double __cdecl log10(double); PALIMPORT double __cdecl modf(double, double*); PALIMPORT double __cdecl pow(double, double); +PALIMPORT double __cdecl scalbn(double, int); PALIMPORT double __cdecl sin(double); PALIMPORT double __cdecl sinh(double); PALIMPORT double __cdecl sqrt(double); @@ -4452,11 +4464,15 @@ 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 fmodf(float, float); +PALIMPORT float __cdecl fmaf(float, float, float); +PALIMPORT int __cdecl ilogbf(float); PALIMPORT float __cdecl logf(float); +PALIMPORT float __cdecl log2f(float); PALIMPORT float __cdecl log10f(float); PALIMPORT float __cdecl modff(float, float*); PALIMPORT float __cdecl powf(float, float); +PALIMPORT float __cdecl scalbnf(float, int); PALIMPORT float __cdecl sinf(float); PALIMPORT float __cdecl sinhf(float); PALIMPORT float __cdecl sqrtf(float); diff --git a/src/pal/src/cruntime/math.cpp b/src/pal/src/cruntime/math.cpp index af2f99416e..126bbff551 100644 --- a/src/pal/src/cruntime/math.cpp +++ b/src/pal/src/cruntime/math.cpp @@ -311,6 +311,44 @@ PALIMPORT double __cdecl PAL_exp(double x) /*++ Function: + fma + +See MSDN. +--*/ +PALIMPORT double __cdecl PAL_fma(double x, double y, double z) +{ + double ret; + PERF_ENTRY(fma); + ENTRY("fma (x=%f, y=%f, z=%f)\n", x, y, z); + + ret = fma(x, y, z); + + LOGEXIT("fma returns double %f\n", ret); + PERF_EXIT(fma); + return ret; +} + +/*++ +Function: + ilogb + +See MSDN. +--*/ +PALIMPORT int __cdecl PAL_ilogb(double x) +{ + int ret; + PERF_ENTRY(ilogb); + ENTRY("ilogb (x=%f)\n", x); + + ret = ilogb(x); + + LOGEXIT("ilogb returns int %d\n", ret); + PERF_EXIT(ilogb); + return ret; +} + +/*++ +Function: labs See MSDN. @@ -360,6 +398,25 @@ PALIMPORT double __cdecl PAL_log(double x) /*++ Function: + log2 + +See MSDN. +--*/ +PALIMPORT double __cdecl PAL_log2(double x) +{ + double ret; + PERF_ENTRY(log2); + ENTRY("log2 (x=%f)\n", x); + + ret = log2(x); + + LOGEXIT("log2 returns double %f\n", ret); + PERF_EXIT(log2); + return ret; +} + +/*++ +Function: log10 See MSDN. @@ -483,6 +540,25 @@ PALIMPORT double __cdecl PAL_pow(double x, double y) /*++ Function: + scalbn + +See MSDN. +--*/ +PALIMPORT double __cdecl PAL_scalbn(double x, int n) +{ + double ret; + PERF_ENTRY(scalbn); + ENTRY("scalbn (x=%f, n=%d)\n", x, n); + + ret = scalbn(x, n); + + LOGEXIT("scalbn returns double %f\n", ret); + PERF_EXIT(scalbn); + return ret; +} + +/*++ +Function: _signbitf Determines whether given single-precision floating point value has a negative sign. @@ -750,6 +826,44 @@ PALIMPORT float __cdecl PAL_expf(float x) /*++ Function: + fmaf + +See MSDN. +--*/ +PALIMPORT float __cdecl PAL_fmaf(float x, float y, float z) +{ + float ret; + PERF_ENTRY(fmaf); + ENTRY("fmaf (x=%f, y=%f, z=%f)\n", x, y, z); + + ret = fmaf(x, y, z); + + LOGEXIT("fma returns float %f\n", ret); + PERF_EXIT(fmaf); + return ret; +} + +/*++ +Function: + ilogbf + +See MSDN. +--*/ +PALIMPORT int __cdecl PAL_ilogbf(float x) +{ + int ret; + PERF_ENTRY(ilogbf); + ENTRY("ilogbf (x=%f)\n", x); + + ret = ilogbf(x); + + LOGEXIT("ilogbf returns int %d\n", ret); + PERF_EXIT(ilogbf); + return ret; +} + +/*++ +Function: logf See MSDN. @@ -780,6 +894,25 @@ PALIMPORT float __cdecl PAL_logf(float x) /*++ Function: + log2f + +See MSDN. +--*/ +PALIMPORT float __cdecl PAL_log2f(float x) +{ + float ret; + PERF_ENTRY(log2f); + ENTRY("log2f (x=%f)\n", x); + + ret = log2f(x); + + LOGEXIT("log2f returns float %f\n", ret); + PERF_EXIT(log2f); + return ret; +} + +/*++ +Function: log10f See MSDN. @@ -894,3 +1027,22 @@ PALIMPORT float __cdecl PAL_powf(float x, float y) PERF_EXIT(powf); return ret; } + +/*++ +Function: + scalbnf + +See MSDN. +--*/ +PALIMPORT float __cdecl PAL_scalbnf(float x, int n) +{ + float ret; + PERF_ENTRY(scalbnf); + ENTRY("scalbnf (x=%f, n=%d)\n", x, n); + + ret = scalbnf(x, n); + + LOGEXIT("scalbnf returns double %f\n", ret); + PERF_EXIT(scalbnf); + return ret; +} diff --git a/src/pal/src/include/pal/palinternal.h b/src/pal/src/include/pal/palinternal.h index 69e4f5fdb9..0e37ba84c0 100644 --- a/src/pal/src/include/pal/palinternal.h +++ b/src/pal/src/include/pal/palinternal.h @@ -461,10 +461,14 @@ function_name() to call the system's implementation #undef fabs #undef floor #undef fmod +#undef fma +#undef ilogb #undef log +#undef log2 #undef log10 #undef modf #undef pow +#undef scalbn #undef sin #undef sinh #undef sqrt @@ -485,10 +489,14 @@ function_name() to call the system's implementation #undef fabsf #undef floorf #undef fmodf +#undef fmaf +#undef ilogbf #undef logf +#undef log2f #undef log10f #undef modff #undef powf +#undef scalbnf #undef sinf #undef sinhf #undef sqrtf diff --git a/src/pal/tests/palsuite/c_runtime/fma/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fma/CMakeLists.txt new file mode 100644 index 0000000000..5e1ef7f28b --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/fma/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/fma/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fma/test1/CMakeLists.txt new file mode 100644 index 0000000000..bb478cbe06 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/fma/test1/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test1.cpp +) + +add_executable(paltest_fma_test1 + ${SOURCES} +) + +add_dependencies(paltest_fma_test1 coreclrpal) + +target_link_libraries(paltest_fma_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/src/pal/tests/palsuite/c_runtime/fma/test1/test1.cpp b/src/pal/tests/palsuite/c_runtime/fma/test1/test1.cpp new file mode 100644 index 0000000000..f6918d6ffd --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/fma/test1/test1.cpp @@ -0,0 +1,151 @@ +// 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 fma returns correct values for a subset of values. +** Tests with positive and negative values of x, y, and z to ensure +** fmaf is returning correct results. +** +**===================================================================*/ + +#include <palsuite.h> + +// binary64 (double) has a machine epsilon of 2^-52 (approx. 2.22e-16). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-50 (approx. 8.88e-16) 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 (15-17 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxxxxxxxxxx will use +// PAL_EPSILON for the variance, while an expected result in the format of 0.0xxxxxxxxxxxxxxxxx +// will use PAL_EPSILON / 10 and and expected result in the format of x.xxxxxxxxxxxxxxxx will +// use PAL_EPSILON * 10. +#define PAL_EPSILON 8.8817841970012523e-16 + +#define PAL_NAN sqrt(-1.0) +#define PAL_POSINF -log(0.0) +#define PAL_NEGINF log(0.0) + +/** + * Helper test structure + */ +struct test +{ + double x; /* first component of the value to test the function with */ + double y; /* second component of the value to test the function with */ + double z; /* third component of the value to test the function with */ + double expected; /* expected result */ + double variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(double x, double y, double z, double expected, double variance) +{ + double result = fma(x, y, z); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + double delta = fabs(result - expected); + + if (delta > variance) + { + Fail("fma(%g, %g, %g) returned %20.17g when it should have returned %20.17g", + x, y, z, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(double x, double y, double z) +{ + double result = fma(x, y, z); + + if (!_isnan(result)) + { + Fail("fma(%g, %g, %g) returned %20.17g when it should have returned %20.17g", + x, y, z, result, PAL_NAN); + } +} + +/** + * main + * + * executable entry point + */ +int __cdecl main(int argc, char **argv) +{ + struct test tests[] = + { + /* x y z expected variance */ + { PAL_NEGINF, PAL_NEGINF, PAL_NEGINF, PAL_NEGINF, 0 }, + { -1e308, 2, 1e300, -1e300, 0 }, + { 1e308, 2, -1e300, 1e300, 0 }, + { PAL_POSINF, 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].z, tests[i].expected, tests[i].variance); + } + + // Returns NaN if x or y is infinite, the other is zero, and z is NaN + validate_isnan(PAL_NEGINF, 0, PAL_NAN); + validate_isnan(PAL_POSINF, 0, PAL_NAN); + validate_isnan(0, PAL_NEGINF, PAL_NAN); + validate_isnan(0, PAL_POSINF, PAL_NAN); + + // Returns NaN if x or y is infinite, the other is zero, and z is not-NaN + validate_isnan(PAL_POSINF, 0, PAL_NEGINF); + validate_isnan(PAL_NEGINF, 0, PAL_NEGINF); + validate_isnan(0, PAL_POSINF, PAL_NEGINF); + validate_isnan(0, PAL_NEGINF, PAL_NEGINF); + + validate_isnan(PAL_POSINF, 0, 0); + validate_isnan(PAL_NEGINF, 0, 0); + validate_isnan(0, PAL_POSINF, 0); + validate_isnan(0, PAL_NEGINF, 0); + + validate_isnan(PAL_POSINF, 0, PAL_POSINF); + validate_isnan(PAL_NEGINF, 0, PAL_POSINF); + validate_isnan(0, PAL_POSINF, PAL_POSINF); + validate_isnan(0, PAL_NEGINF, PAL_POSINF); + + // Returns NaN if (x * y) is infinite, and z is an infinite of the opposite sign + validate_isnan(PAL_POSINF, PAL_POSINF, PAL_NEGINF); + validate_isnan(PAL_NEGINF, PAL_NEGINF, PAL_POSINF); + validate_isnan(PAL_POSINF, PAL_NEGINF, PAL_POSINF); + validate_isnan(PAL_NEGINF, PAL_POSINF, PAL_POSINF); + + validate_isnan(PAL_POSINF, 1, PAL_NEGINF); + validate_isnan(PAL_NEGINF, 1, PAL_POSINF); + validate_isnan(PAL_POSINF, 1, PAL_POSINF); + validate_isnan(PAL_NEGINF, 1, PAL_POSINF); + + validate_isnan(1, PAL_POSINF, PAL_NEGINF); + validate_isnan(1, PAL_NEGINF, PAL_POSINF); + validate_isnan(1, PAL_NEGINF, PAL_POSINF); + validate_isnan(1, PAL_POSINF, PAL_POSINF); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/fma/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/fma/test1/testinfo.dat new file mode 100644 index 0000000000..22bf0e70a1 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/fma/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 = fma +Name = Call fma with some std input/output. +TYPE = DEFAULT +EXE1 = test1 +Description += Call the fma function with various num/exponent pairs += that should produce std answers. + + + + diff --git a/src/pal/tests/palsuite/c_runtime/fmaf/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fmaf/CMakeLists.txt new file mode 100644 index 0000000000..5e1ef7f28b --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/fmaf/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/fmaf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fmaf/test1/CMakeLists.txt new file mode 100644 index 0000000000..d723d324d4 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/fmaf/test1/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test1.c +) + +add_executable(paltest_fmaf_test1 + ${SOURCES} +) + +add_dependencies(paltest_fmaf_test1 coreclrpal) + +target_link_libraries(paltest_fmaf_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/src/pal/tests/palsuite/c_runtime/fmaf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/fmaf/test1/test1.c new file mode 100644 index 0000000000..7c3b5e391b --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/fmaf/test1/test1.c @@ -0,0 +1,150 @@ +// 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 fmaf returns correct values for a subset of values. +** Tests with positive and negative values of x, y, and z to ensure +** fmaf is returning correct results. +** +**===================================================================*/ + +#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 z; /* third 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 z, float expected, float variance) +{ + float result = fmaf(x, y, z); + + /* + * 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("fmaf(%g, %g, %g) returned %10.9g when it should have returned %10.9g", + x, y, z, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(float x, float y, float z) +{ + float result = fmaf(x, y, z); + + if (!_isnanf(result)) + { + Fail("fmaf(%g, %g, %g) returned %10.9g when it should have returned %10.9g", + x, y, z, result, PAL_NAN); + } +} + +/** + * main + * + * executable entry point + */ +int __cdecl main(int argc, char **argv) +{ + struct test tests[] = + { + /* x y z expected variance */ + { PAL_NEGINF, PAL_NEGINF, PAL_NEGINF, PAL_NEGINF, 0 }, + { -1e38, 2, 1e38, -1e38, 0 }, + { 1e38, 2, -1e38, 1e38, 0 }, + { PAL_POSINF, 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].z, tests[i].expected, tests[i].variance); + } + + // Returns NaN if x or y is infinite, the other is zero, and z is NaN + validate_isnan(PAL_NEGINF, 0, PAL_NAN); + validate_isnan(PAL_POSINF, 0, PAL_NAN); + validate_isnan(0, PAL_NEGINF, PAL_NAN); + validate_isnan(0, PAL_POSINF, PAL_NAN); + + // Returns NaN if x or y is infinite, the other is zero, and z is not-NaN + validate_isnan(PAL_POSINF, 0, PAL_NEGINF); + validate_isnan(PAL_NEGINF, 0, PAL_NEGINF); + validate_isnan(0, PAL_POSINF, PAL_NEGINF); + validate_isnan(0, PAL_NEGINF, PAL_NEGINF); + + validate_isnan(PAL_POSINF, 0, 0); + validate_isnan(PAL_NEGINF, 0, 0); + validate_isnan(0, PAL_POSINF, 0); + validate_isnan(0, PAL_NEGINF, 0); + + validate_isnan(PAL_POSINF, 0, PAL_POSINF); + validate_isnan(PAL_NEGINF, 0, PAL_POSINF); + validate_isnan(0, PAL_POSINF, PAL_POSINF); + validate_isnan(0, PAL_NEGINF, PAL_POSINF); + + // Returns NaN if (x * y) is infinite, and z is an infinite of the opposite sign + validate_isnan(PAL_POSINF, PAL_POSINF, PAL_NEGINF); + validate_isnan(PAL_NEGINF, PAL_NEGINF, PAL_POSINF); + validate_isnan(PAL_POSINF, PAL_NEGINF, PAL_POSINF); + validate_isnan(PAL_NEGINF, PAL_POSINF, PAL_POSINF); + + validate_isnan(PAL_POSINF, 1, PAL_NEGINF); + validate_isnan(PAL_NEGINF, 1, PAL_POSINF); + validate_isnan(PAL_POSINF, 1, PAL_POSINF); + validate_isnan(PAL_NEGINF, 1, PAL_POSINF); + + validate_isnan(1, PAL_POSINF, PAL_NEGINF); + validate_isnan(1, PAL_NEGINF, PAL_POSINF); + validate_isnan(1, PAL_NEGINF, PAL_POSINF); + validate_isnan(1, PAL_POSINF, PAL_POSINF); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/fmaf/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/fmaf/test1/testinfo.dat new file mode 100644 index 0000000000..8ca9fb7330 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/fmaf/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 = fmaf +Name = Call fmaf with some std input/output. +TYPE = DEFAULT +EXE1 = test1 +Description += Call the fmaf function with various num/expfonent pairs += that should produce std answers. + + + + diff --git a/src/pal/tests/palsuite/c_runtime/ilogb/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/ilogb/CMakeLists.txt new file mode 100644 index 0000000000..5e1ef7f28b --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/ilogb/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/ilogb/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/ilogb/test1/CMakeLists.txt new file mode 100644 index 0000000000..8df690836f --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/ilogb/test1/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test1.cpp +) + +add_executable(paltest_ilogb_test1 + ${SOURCES} +) + +add_dependencies(paltest_ilogb_test1 coreclrpal) + +target_link_libraries(paltest_ilogb_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/src/pal/tests/palsuite/c_runtime/ilogb/test1/test1.cpp b/src/pal/tests/palsuite/c_runtime/ilogb/test1/test1.cpp new file mode 100644 index 0000000000..5df6fcf355 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/ilogb/test1/test1.cpp @@ -0,0 +1,101 @@ +// 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 ilogb returns correct values. +** +**===================================================================*/ + +#include <palsuite.h> + +#define PAL_NAN sqrt(-1.0) +#define PAL_POSINF -log(0.0) +#define PAL_NEGINF log(0.0) + +/** + * Helper test structure + */ +struct test +{ + double value; /* value to test the function with */ + int expected; /* expected result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(double value, int expected) +{ + int result = ilogb(value); + + if (result != expected) + { + Fail("ilogb(%g) returned %10.10g when it should have returned %10.10g", + value, result, expected); + } +} + +/** + * main + * + * executable entry point + */ +int __cdecl main(int argc, char **argv) +{ + struct test tests[] = + { + /* value expected */ + { PAL_NEGINF, 0x80000000 }, + { 0, 0x80000000 }, + { PAL_POSINF, 0x80000000 }, + { 0.11331473229676087, -3 }, // expected: -(pi) + { 0.15195522325791297, -2 }, // expected: -(e) + { 0.20269956628651730, -2 }, // expected: -(ln(10)) + { 0.33662253682241906, -1 }, // expected: -(pi / 2) + { 0.36787944117144232, -1 }, // expected: -(log2(e)) + { 0.37521422724648177, -1 }, // expected: -(sqrt(2)) + { 0.45742934732229695, -1 }, // expected: -(2 / sqrt(pi)) + { 0.5, -1 }, // expected: -(1) + { 0.58019181037172444, 0 }, // expected: -(pi / 4) + { 0.61254732653606592, 0 }, // expected: -(1 / sqrt(2)) + { 0.61850313780157598, 0 }, // expected: -(ln(2)) + { 0.64321824193300488, 0 }, // expected: -(2 / pi) + { 0.74005557395545179, 0 }, // expected: -(log10(e)) + { 0.80200887896145195, 0 }, // expected: -(1 / pi) + { 1, 0 }, + { 1.2468689889006383, 0 }, // expected: 1 / pi + { 1.3512498725672678, 0 }, // expected: log10(e) + { 1.5546822754821001, 0 }, // expected: 2 / pi + { 1.6168066722416747, 0 }, // expected: ln(2) + { 1.6325269194381528, 0 }, // expected: 1 / sqrt(2) + { 1.7235679341273495, 0 }, // expected: pi / 4 + { 2, 1 }, + { 2.1861299583286618, 1 }, // expected: 2 / sqrt(pi) + { 2.6651441426902252, 1 }, // expected: sqrt(2) + { 2.7182818284590452, 1 }, // expected: log2(e) value: e + { 2.9706864235520193, 1 }, // expected: pi / 2 + { 4.9334096679145963, 2 }, // expected: ln(10) + { 6.5808859910179210, 2 }, // expected: e + { 8.8249778270762876, 3 }, // expected: pi + { PAL_NAN, 2147483647 }, + }; + + 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); + } + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/ilogb/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/ilogb/test1/testinfo.dat new file mode 100644 index 0000000000..05549dbd2f --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/ilogb/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 = ilogb +Name = Call ilogb with some std input/output. +TYPE = DEFAULT +EXE1 = test1 +Description += Call the ilogb function with various num/exponent pairs += that should produce std answers. + + + + diff --git a/src/pal/tests/palsuite/c_runtime/ilogbf/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/ilogbf/CMakeLists.txt new file mode 100644 index 0000000000..5e1ef7f28b --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/ilogbf/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/ilogbf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/ilogbf/test1/CMakeLists.txt new file mode 100644 index 0000000000..b478f698fc --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/ilogbf/test1/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test1.c +) + +add_executable(paltest_ilogbf_test1 + ${SOURCES} +) + +add_dependencies(paltest_ilogbf_test1 coreclrpal) + +target_link_libraries(paltest_ilogbf_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/src/pal/tests/palsuite/c_runtime/ilogbf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/ilogbf/test1/test1.c new file mode 100644 index 0000000000..2b97e444f4 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/ilogbf/test1/test1.c @@ -0,0 +1,101 @@ +// 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 ilogbf returns correct values. +** +**===================================================================*/ + +#include <palsuite.h> + +#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 */ + int expected; /* expected result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(float value, int expected) +{ + float result = ilogbf(value); + + if (result != expected) + { + Fail("ilogbf(%g) returned %10.10g when it should have returned %10.10g", + value, result, expected); + } +} + +/** + * main + * + * executable entry point + */ +int __cdecl main(int argc, char **argv) +{ + struct test tests[] = + { + /* value expected */ + { PAL_NEGINF, 0x80000000 }, + { 0, 0x80000000 }, + { PAL_POSINF, 0x80000000 }, + { 0.113314732f, -3 }, // expected: -(pi) + { 0.151955223f, -2 }, // expected: -(e) + { 0.202699566f, -2 }, // expected: -(ln(10)) + { 0.336622537f, -1 }, // expected: -(pi / 2) + { 0.367879441f, -1 }, // expected: -(log2(e)) + { 0.375214227f, -1 }, // expected: -(sqrt(2)) + { 0.457429347f, -1 }, // expected: -(2 / sqrt(pi)) + { 0.5f, -1 }, // expected: -(1) + { 0.580191810f, 0 }, // expected: -(pi / 4) + { 0.612547327f, 0 }, // expected: -(1 / sqrt(2)) + { 0.618503138f, 0 }, // expected: -(ln(2)) + { 0.643218242f, 0 }, // expected: -(2 / pi) + { 0.740055574f, 0 }, // expected: -(log10(e)) + { 0.802008879f, 0 }, // expected: -(1 / pi) + { 1, 0 }, + { 1.24686899f, 0 }, // expected: 1 / pi + { 1.35124987f, 0 }, // expected: log10(e) + { 1.55468228f, 0 }, // expected: 2 / pi + { 1.61680667f, 0 }, // expected: ln(2) + { 1.63252692f, 0 }, // expected: 1 / sqrt(2) + { 1.72356793f, 0 }, // expected: pi / 4 + { 2, 1 }, + { 2.18612996f, 1 }, // expected: 2 / sqrt(pi) + { 2.66514414f, 1 }, // expected: sqrt(2) + { 2.71828183f, 1 }, // expected: log2(e) value: e + { 2.97068642f, 1 }, // expected: pi / 2 + { 4.93340967f, 2 }, // expected: ln(10) + { 6.58088599f, 2 }, // expected: e + { 8.82497783f, 3 }, // expected: pi + { PAL_NAN, 2147483647 }, + }; + + 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); + } + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/ilogbf/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/ilogbf/test1/testinfo.dat new file mode 100644 index 0000000000..8337bba44d --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/ilogbf/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 = ilogbf +Name = Call ilogbf with some std input/output. +TYPE = DEFAULT +EXE1 = test1 +Description += Call the ilogbf function with various num/expfonent pairs += that should produce std answers. + + + + diff --git a/src/pal/tests/palsuite/c_runtime/log2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/log2/CMakeLists.txt new file mode 100644 index 0000000000..5e1ef7f28b --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/log2/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/log2/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/log2/test1/CMakeLists.txt new file mode 100644 index 0000000000..ea0c178a47 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/log2/test1/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test1.cpp +) + +add_executable(paltest_log2_test1 + ${SOURCES} +) + +add_dependencies(paltest_log2_test1 coreclrpal) + +target_link_libraries(paltest_log2_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/src/pal/tests/palsuite/c_runtime/log2/test1/test1.cpp b/src/pal/tests/palsuite/c_runtime/log2/test1/test1.cpp new file mode 100644 index 0000000000..c7900a0a93 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/log2/test1/test1.cpp @@ -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 that log2 returns correct values. +** +**===================================================================*/ + +#include <palsuite.h> + +// binary64 (double) has a machine epsilon of 2^-52 (approx. 2.22e-16). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-50 (approx. 8.88e-16) 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 (15-17 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxxxxxxxxxx will use +// PAL_EPSILON for the variance, while an expected result in the format of 0.0xxxxxxxxxxxxxxxxx +// will use PAL_EPSILON / 10 and and expected result in the format of x.xxxxxxxxxxxxxxxx will +// use PAL_EPSILON * 10. +#define PAL_EPSILON 8.8817841970012523e-16 + +#define PAL_NAN sqrt(-1.0) +#define PAL_POSINF -log(0.0) +#define PAL_NEGINF log(0.0) + +/** + * Helper test structure + */ +struct test +{ + double value; /* value to test the function with */ + double expected; /* expected result */ + double variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(double value, double expected, double variance) +{ + double result = log2(value); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + double delta = fabs(result - expected); + + if (delta > variance) + { + Fail("log2(%g) returned %20.17g when it should have returned %20.17g", + value, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(double value) +{ + double result = log2(value); + + if (!_isnan(result)) + { + Fail("log2(%g) returned %20.17g when it should have returned %20.17g", + 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.11331473229676087, -3.1415926535897932, PAL_EPSILON * 10 }, // expected: -(pi) + { 0.15195522325791297, -2.7182818284590452, PAL_EPSILON * 10 }, // expected: -(e) + { 0.20269956628651730, -2.3025850929940457, PAL_EPSILON * 10 }, // expected: -(ln(10)) + { 0.33662253682241906, -1.5707963267948966, PAL_EPSILON * 10 }, // expected: -(pi / 2) + { 0.36787944117144232, -1.4426950408889634, PAL_EPSILON * 10 }, // expected: -(log2(e)) + { 0.37521422724648177, -1.4142135623730950, PAL_EPSILON * 10 }, // expected: -(sqrt(2)) + { 0.45742934732229695, -1.1283791670955126, PAL_EPSILON * 10 }, // expected: -(2 / sqrt(pi)) + { 0.5, -1, PAL_EPSILON * 10 }, // expected: -(1) + { 0.58019181037172444, -0.78539816339744831, PAL_EPSILON }, // expected: -(pi / 4) + { 0.61254732653606592, -0.70710678118654752, PAL_EPSILON }, // expected: -(1 / sqrt(2)) + { 0.61850313780157598, -0.69314718055994531, PAL_EPSILON }, // expected: -(ln(2)) + { 0.64321824193300488, -0.63661977236758134, PAL_EPSILON }, // expected: -(2 / pi) + { 0.74005557395545179, -0.43429448190325183, PAL_EPSILON }, // expected: -(log10(e)) + { 0.80200887896145195, -0.31830988618379067, PAL_EPSILON }, // expected: -(1 / pi) + { 1, 0, PAL_EPSILON }, + { 1.2468689889006383, 0.31830988618379067, PAL_EPSILON }, // expected: 1 / pi + { 1.3512498725672678, 0.43429448190325183, PAL_EPSILON }, // expected: log10(e) + { 1.5546822754821001, 0.63661977236758134, PAL_EPSILON }, // expected: 2 / pi + { 1.6168066722416747, 0.69314718055994531, PAL_EPSILON }, // expected: ln(2) + { 1.6325269194381528, 0.70710678118654752, PAL_EPSILON }, // expected: 1 / sqrt(2) + { 1.7235679341273495, 0.78539816339744831, PAL_EPSILON }, // expected: pi / 4 + { 2, 1, PAL_EPSILON * 10 }, + { 2.1861299583286618, 1.1283791670955126, PAL_EPSILON * 10 }, // expected: 2 / sqrt(pi) + { 2.6651441426902252, 1.4142135623730950, PAL_EPSILON * 10 }, // expected: sqrt(2) + { 2.7182818284590452, 1.4426950408889634, PAL_EPSILON * 10 }, // expected: log2(e) value: e + { 2.9706864235520193, 1.5707963267948966, PAL_EPSILON * 10 }, // expected: pi / 2 + { 4.9334096679145963, 2.3025850929940457, PAL_EPSILON * 10 }, // expected: ln(10) + { 6.5808859910179210, 2.7182818284590452, PAL_EPSILON * 10 }, // expected: e + { 8.8249778270762876, 3.1415926535897932, 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].x, tests[i].y, tests[i].z, 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/log2/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/log2/test1/testinfo.dat new file mode 100644 index 0000000000..ef6268e079 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/log2/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 = log2 +Name = Call log2 with some std input/output. +TYPE = DEFAULT +EXE1 = test1 +Description += Call the log2 function with various num/exponent pairs += that should produce std answers. + + + + diff --git a/src/pal/tests/palsuite/c_runtime/log2f/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/log2f/CMakeLists.txt new file mode 100644 index 0000000000..5e1ef7f28b --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/log2f/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/log2f/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/log2f/test1/CMakeLists.txt new file mode 100644 index 0000000000..bee20844ab --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/log2f/test1/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test1.c +) + +add_executable(paltest_log2f_test1 + ${SOURCES} +) + +add_dependencies(paltest_log2f_test1 coreclrpal) + +target_link_libraries(paltest_log2f_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/src/pal/tests/palsuite/c_runtime/log2f/test1/test1.c b/src/pal/tests/palsuite/c_runtime/log2f/test1/test1.c new file mode 100644 index 0000000000..5231aa5fcc --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/log2f/test1/test1.c @@ -0,0 +1,138 @@ +// 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 log2f returns correct 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 = log2f(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("log2f(%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 = log2f(value); + + if (!_isnanf(result)) + { + Fail("log2f(%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.113314732f, -3.14159265f, PAL_EPSILON * 10 }, // expected: -(pi) + { 0.151955223f, -2.71828183f, PAL_EPSILON * 10 }, // expected: -(e) + { 0.202699566f, -2.30258509f, PAL_EPSILON * 10 }, // expected: -(ln(10)) + { 0.336622537f, -1.57079633f, PAL_EPSILON * 10 }, // expected: -(pi / 2) + { 0.367879441f, -1.44269504f, PAL_EPSILON * 10 }, // expected: -(logf2(e)) + { 0.375214227f, -1.41421356f, PAL_EPSILON * 10 }, // expected: -(sqrtf(2)) + { 0.457429347f, -1.12837917f, PAL_EPSILON * 10 }, // expected: -(2 / sqrtf(pi)) + { 0.5f, -1, PAL_EPSILON * 10 }, // expected: -(1) + { 0.580191810f, -0.785398163f, PAL_EPSILON }, // expected: -(pi / 4) + { 0.612547327f, -0.707106781f, PAL_EPSILON }, // expected: -(1 / sqrtf(2)) + { 0.618503138f, -0.693147181f, PAL_EPSILON }, // expected: -(ln(2)) + { 0.643218242f, -0.636619772f, PAL_EPSILON }, // expected: -(2 / pi) + { 0.740055574f, -0.434294482f, PAL_EPSILON }, // expected: -(log10f(e)) + { 0.802008879f, -0.318309886f, PAL_EPSILON }, // expected: -(1 / pi) + { 1, 0, PAL_EPSILON }, + { 1.24686899f, 0.318309886f, PAL_EPSILON }, // expected: 1 / pi + { 1.35124987f, 0.434294482f, PAL_EPSILON }, // expected: log10f(e) value: e + { 1.55468228f, 0.636619772f, PAL_EPSILON }, // expected: 2 / pi + { 1.61680667f, 0.693147181f, PAL_EPSILON }, // expected: ln(2) + { 1.63252692f, 0.707106781f, PAL_EPSILON }, // expected: 1 / sqrtf(2) + { 1.72356793f, 0.785398163f, PAL_EPSILON }, // expected: pi / 4 + { 2, 1, PAL_EPSILON * 10 }, + { 2.18612996f, 1.12837917f, PAL_EPSILON * 10 }, // expected: 2 / sqrtf(pi) + { 2.66514414f, 1.41421356f, PAL_EPSILON * 10 }, // expected: sqrtf(2) + { 2.71828183f, 1.44269504f, PAL_EPSILON * 10 }, // expected: logf2(e) + { 2.97068642f, 1.57079633f, PAL_EPSILON * 10 }, // expected: pi / 2 + { 4.93340967f, 2.30258509f, PAL_EPSILON * 10 }, // expected: ln(10) + { 6.58088599f, 2.71828183f, PAL_EPSILON * 10 }, // expected: e + { 8.82497783f, 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].x, tests[i].y, tests[i].z, 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/log2f/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/log2f/test1/testinfo.dat new file mode 100644 index 0000000000..7627c825c7 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/log2f/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 = log2f +Name = Call log2f with some std input/output. +TYPE = DEFAULT +EXE1 = test1 +Description += Call the log2f function with various num/expfonent pairs += that should produce std answers. + + + + diff --git a/src/pal/tests/palsuite/c_runtime/scalbn/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/scalbn/CMakeLists.txt new file mode 100644 index 0000000000..5e1ef7f28b --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/scalbn/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/scalbn/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/scalbn/test1/CMakeLists.txt new file mode 100644 index 0000000000..083cd113a4 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/scalbn/test1/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test1.cpp +) + +add_executable(paltest_scalbn_test1 + ${SOURCES} +) + +add_dependencies(paltest_scalbn_test1 coreclrpal) + +target_link_libraries(paltest_scalbn_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/src/pal/tests/palsuite/c_runtime/scalbn/test1/test1.cpp b/src/pal/tests/palsuite/c_runtime/scalbn/test1/test1.cpp new file mode 100644 index 0000000000..9507cc4886 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/scalbn/test1/test1.cpp @@ -0,0 +1,140 @@ +// 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 scalbn returns correct values. +** +**===================================================================*/ + +#include <palsuite.h> + +// binary64 (double) has a machine epsilon of 2^-52 (approx. 2.22e-16). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-50 (approx. 8.88e-16) 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 (15-17 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxxxxxxxxxx will use +// PAL_EPSILON for the variance, while an expected result in the format of 0.0xxxxxxxxxxxxxxxxx +// will use PAL_EPSILON / 10 and and expected result in the format of x.xxxxxxxxxxxxxxxx will +// use PAL_EPSILON * 10. +#define PAL_EPSILON 8.8817841970012523e-16 + +#define PAL_NAN sqrt(-1.0) +#define PAL_POSINF -log(0.0) +#define PAL_NEGINF log(0.0) + +/** + * Helper test structure + */ +struct test +{ + double value; /* value to test the function with */ + int exponent; /* exponent to test the function with */ + double expected; /* expected result */ + double variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(double value, int exponent, double expected, double variance) +{ + double result = scalbn(value, exponent); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + double delta = fabs(result - expected); + + if (delta > variance) + { + Fail("scalbn(%g, %d) returned %20.17g when it should have returned %20.17g\n", + value, exponent, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(double value, int exponent) +{ + double result = scalbn(value, exponent); + + if (!_isnan(result)) + { + Fail("scalbn(%g, %d) returned %20.17g when it should have returned %20.17g\n", + value, exponent, result, PAL_NAN); + } +} + +/** + * main + * + * executable entry point + */ +int __cdecl main(int argc, char **argv) +{ + struct test tests[] = + { + /* value exponent expected variance */ + { PAL_NEGINF, 0x80000000, PAL_NEGINF, 0 }, + { 0, 0x80000000, 0, 0 }, + { 0.11331473229676087, -3, 0.014164341537095108, PAL_EPSILON / 10 }, + { 0.15195522325791297, -2, 0.037988805814478242, PAL_EPSILON / 10 }, + { 0.20269956628651730, -2, 0.050674891571629327, PAL_EPSILON / 10 }, + { 0.33662253682241906, -1, 0.16831126841120952, PAL_EPSILON }, + { 0.36787944117144232, -1, 0.18393972058572117, PAL_EPSILON }, + { 0.37521422724648177, -1, 0.1876071136232409, PAL_EPSILON }, + { 0.45742934732229695, -1, 0.22871467366114848, PAL_EPSILON }, + { 0.5, -1, 0.25, PAL_EPSILON }, + { 0.58019181037172444, 0, 0.5801918103717244, PAL_EPSILON }, + { 0.61254732653606592, 0, 0.61254732653606592, PAL_EPSILON }, + { 0.61850313780157598, 0, 0.61850313780157595, PAL_EPSILON }, + { 0.64321824193300488, 0, 0.64321824193300492, PAL_EPSILON }, + { 0.74005557395545179, 0, 0.74005557395545174, PAL_EPSILON }, + { 0.80200887896145195, 0, 0.8020088789614519, PAL_EPSILON }, + { 1, 0, 1, PAL_EPSILON * 10 }, + { 1.2468689889006383, 0, 1.2468689889006384, PAL_EPSILON * 10 }, + { 1.3512498725672678, 0, 1.3512498725672677, PAL_EPSILON * 10 }, + { 1.5546822754821001, 0, 1.5546822754821001, PAL_EPSILON * 10 }, + { 1.6168066722416747, 0, 1.6168066722416747, PAL_EPSILON * 10 }, + { 1.6325269194381528, 0, 1.6325269194381529, PAL_EPSILON * 10 }, + { 1.7235679341273495, 0, 1.7235679341273495, PAL_EPSILON * 10 }, + { 2, 1, 4, PAL_EPSILON * 10 }, + { 2.1861299583286618, 1, 4.3722599166573239, PAL_EPSILON * 10 }, + { 2.6651441426902252, 1, 5.3302882853804503, PAL_EPSILON * 10 }, + { 2.7182818284590452, 1, 5.4365636569180902, PAL_EPSILON * 10 }, + { 2.9706864235520193, 1, 5.9413728471040388, PAL_EPSILON * 10 }, + { 4.9334096679145963, 2, 19.733638671658387, PAL_EPSILON * 100 }, + { 6.5808859910179210, 2, 26.323543964071686, PAL_EPSILON * 100 }, + { 8.8249778270762876, 3, 70.599822616610297, PAL_EPSILON * 100 }, + { PAL_POSINF, 0x80000000, 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].exponent, tests[i].expected, tests[i].variance); + } + + validate_isnan(PAL_NAN, 2147483647); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/scalbn/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/scalbn/test1/testinfo.dat new file mode 100644 index 0000000000..ce98062b65 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/scalbn/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 = scalbn +Name = Call scalbn with some std input/output. +TYPE = DEFAULT +EXE1 = test1 +Description += Call the scalbn function with various num/exponent pairs += that should produce std answers. + + + + diff --git a/src/pal/tests/palsuite/c_runtime/scalbnf/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/scalbnf/CMakeLists.txt new file mode 100644 index 0000000000..5e1ef7f28b --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/scalbnf/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/scalbnf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/scalbnf/test1/CMakeLists.txt new file mode 100644 index 0000000000..e14b54abae --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/scalbnf/test1/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test1.c +) + +add_executable(paltest_scalbnf_test1 + ${SOURCES} +) + +add_dependencies(paltest_scalbnf_test1 coreclrpal) + +target_link_libraries(paltest_scalbnf_test1 + ${COMMON_TEST_LIBRARIES} +) diff --git a/src/pal/tests/palsuite/c_runtime/scalbnf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/scalbnf/test1/test1.c new file mode 100644 index 0000000000..88f00a2484 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/scalbnf/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 that scalbnf returns correct 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 */ + int exponent; /* exponent 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, int exponent, float expected, float variance) +{ + float result = scalbnf(value, exponent); + + /* + * 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("scalbnf(%g, %g) returned %10.9g when it should have returned %10.9g", + value, exponent, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(float value, int exponent) +{ + float result = scalbnf(value, exponent); + + if (!_isnanf(result)) + { + Fail("scalbnf(%g, %g) returned %10.9g when it should have returned %10.9g", + value, exponent, result, PAL_NAN); + } +} + +/** + * main + * + * executable entry point + */ +int __cdecl main(int argc, char **argv) +{ + struct test tests[] = + { + /* value exponent expected variance */ + { PAL_NEGINF, 0x80000000, PAL_NEGINF, 0 }, + { 0, 0x80000000, 0, 0 }, + { 0.113314732f, -3, 0.0141643415f, PAL_EPSILON / 10 }, + { 0.151955223f, -2, 0.0379888058f, PAL_EPSILON / 10 }, + { 0.202699566f, -2, 0.0506748916f, PAL_EPSILON / 10 }, + { 0.336622537f, -1, 0.168311268f, PAL_EPSILON }, + { 0.367879441f, -1, 0.183939721f, PAL_EPSILON }, + { 0.375214227f, -1, 0.187607114f, PAL_EPSILON }, + { 0.457429347f, -1, 0.228714674f, PAL_EPSILON }, + { 0.5f, -1, 0.25f, PAL_EPSILON }, + { 0.580191810f, 0, 0.580191810f, PAL_EPSILON }, + { 0.612547327f, 0, 0.612547327f, PAL_EPSILON }, + { 0.618503138f, 0, 0.618503138f, PAL_EPSILON }, + { 0.643218242f, 0, 0.643218242f, PAL_EPSILON }, + { 0.740055574f, 0, 0.740055574f, PAL_EPSILON }, + { 0.802008879f, 0, 0.802008879f, PAL_EPSILON }, + { 1, 0, 1, PAL_EPSILON * 10 }, + { 1.24686899f, 0, 1.24686899f, PAL_EPSILON * 10 }, + { 1.35124987f, 0, 1.35124987f, PAL_EPSILON * 10 }, + { 1.55468228f, 0, 1.55468228f, PAL_EPSILON * 10 }, + { 1.61680667f, 0, 1.61680667f, PAL_EPSILON * 10 }, + { 1.63252692f, 0, 1.63252692f, PAL_EPSILON * 10 }, + { 1.72356793f, 0, 1.72356793f, PAL_EPSILON * 10 }, + { 2, 1, 4, PAL_EPSILON * 10 }, + { 2.18612996f, 1, 4.37225992f, PAL_EPSILON * 10 }, + { 2.66514414f, 1, 5.33028829f, PAL_EPSILON * 10 }, + { 2.71828183f, 1, 5.43656366f, PAL_EPSILON * 10 }, + { 2.97068642f, 1, 5.94137285f, PAL_EPSILON * 10 }, + { 4.93340967f, 2, 19.7336387f, PAL_EPSILON * 100 }, + { 6.58088599f, 2, 26.3235440f, PAL_EPSILON * 100 }, + { 8.82497783f, 3, 70.5998226f, PAL_EPSILON * 100 }, + { PAL_POSINF, 0x80000000, 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].exponent, tests[i].expected, tests[i].variance); + } + + validate_isnan(PAL_NAN, 2147483647); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/scalbnf/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/scalbnf/test1/testinfo.dat new file mode 100644 index 0000000000..728fafabae --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/scalbnf/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 = scalbnf +Name = Call scalbnf with some std input/output. +TYPE = DEFAULT +EXE1 = test1 +Description += Call the scalbnf function with various num/expfonent pairs += that should produce std answers. + + + + |