summaryrefslogtreecommitdiff
path: root/src/pal
diff options
context:
space:
mode:
authorTanner Gooding <tagoo@outlook.com>2018-11-05 15:37:36 -0800
committerGitHub <noreply@github.com>2018-11-05 15:37:36 -0800
commit28417584d8e98ae7eac22e92b952778f8ea94047 (patch)
treea6010a24228ca769fc7a6381cbd04b3a762e9219 /src/pal
parentd3a7c973723bf2610c7dcdcd00318c06a72a36f8 (diff)
downloadcoreclr-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')
-rw-r--r--src/pal/inc/pal.h18
-rw-r--r--src/pal/src/cruntime/math.cpp152
-rw-r--r--src/pal/src/include/pal/palinternal.h8
-rw-r--r--src/pal/tests/palsuite/c_runtime/fma/CMakeLists.txt3
-rw-r--r--src/pal/tests/palsuite/c_runtime/fma/test1/CMakeLists.txt17
-rw-r--r--src/pal/tests/palsuite/c_runtime/fma/test1/test1.cpp151
-rw-r--r--src/pal/tests/palsuite/c_runtime/fma/test1/testinfo.dat17
-rw-r--r--src/pal/tests/palsuite/c_runtime/fmaf/CMakeLists.txt3
-rw-r--r--src/pal/tests/palsuite/c_runtime/fmaf/test1/CMakeLists.txt17
-rw-r--r--src/pal/tests/palsuite/c_runtime/fmaf/test1/test1.c150
-rw-r--r--src/pal/tests/palsuite/c_runtime/fmaf/test1/testinfo.dat17
-rw-r--r--src/pal/tests/palsuite/c_runtime/ilogb/CMakeLists.txt3
-rw-r--r--src/pal/tests/palsuite/c_runtime/ilogb/test1/CMakeLists.txt17
-rw-r--r--src/pal/tests/palsuite/c_runtime/ilogb/test1/test1.cpp101
-rw-r--r--src/pal/tests/palsuite/c_runtime/ilogb/test1/testinfo.dat17
-rw-r--r--src/pal/tests/palsuite/c_runtime/ilogbf/CMakeLists.txt3
-rw-r--r--src/pal/tests/palsuite/c_runtime/ilogbf/test1/CMakeLists.txt17
-rw-r--r--src/pal/tests/palsuite/c_runtime/ilogbf/test1/test1.c101
-rw-r--r--src/pal/tests/palsuite/c_runtime/ilogbf/test1/testinfo.dat17
-rw-r--r--src/pal/tests/palsuite/c_runtime/log2/CMakeLists.txt3
-rw-r--r--src/pal/tests/palsuite/c_runtime/log2/test1/CMakeLists.txt17
-rw-r--r--src/pal/tests/palsuite/c_runtime/log2/test1/test1.cpp139
-rw-r--r--src/pal/tests/palsuite/c_runtime/log2/test1/testinfo.dat17
-rw-r--r--src/pal/tests/palsuite/c_runtime/log2f/CMakeLists.txt3
-rw-r--r--src/pal/tests/palsuite/c_runtime/log2f/test1/CMakeLists.txt17
-rw-r--r--src/pal/tests/palsuite/c_runtime/log2f/test1/test1.c138
-rw-r--r--src/pal/tests/palsuite/c_runtime/log2f/test1/testinfo.dat17
-rw-r--r--src/pal/tests/palsuite/c_runtime/scalbn/CMakeLists.txt3
-rw-r--r--src/pal/tests/palsuite/c_runtime/scalbn/test1/CMakeLists.txt17
-rw-r--r--src/pal/tests/palsuite/c_runtime/scalbn/test1/test1.cpp140
-rw-r--r--src/pal/tests/palsuite/c_runtime/scalbn/test1/testinfo.dat17
-rw-r--r--src/pal/tests/palsuite/c_runtime/scalbnf/CMakeLists.txt3
-rw-r--r--src/pal/tests/palsuite/c_runtime/scalbnf/test1/CMakeLists.txt17
-rw-r--r--src/pal/tests/palsuite/c_runtime/scalbnf/test1/test1.c139
-rw-r--r--src/pal/tests/palsuite/c_runtime/scalbnf/test1/testinfo.dat17
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.
+
+
+
+