[CRT_APITEST] Implement tests for fabs/fabsf

This commit is contained in:
Timo Kreuzer 2021-08-04 17:22:01 +02:00
parent 96b847fd04
commit 8a67170616
6 changed files with 204 additions and 2 deletions

View file

@ -0,0 +1,112 @@
/*
* PROJECT: ReactOS api tests
* LICENSE: MIT (https://spdx.org/licenses/MIT)
* PURPOSE: Tests for fabs / fabsf
* COPYRIGHT: Copyright 2021 Timo Kreuzer <timo.kreuzer@reactos.org>
*/
/* Don't use the inline ceilf, unless required */
#if defined(TEST_STATIC_CRT) || defined(_M_ARM)
#define _CRTBLD
#endif
#include "math_helpers.h"
#ifdef _MSC_VER
#pragma function(fabs)
// fabsf is not available as an intrinsic
#endif
static TESTENTRY_DBL s_fabs_tests[] =
{
/* Special values */
{ 0x7FF0000000000000ull /* INF */, 0x7FF0000000000000ull /* INF */ },
#ifdef _M_AMD64
{ 0x7FF0000000000001ull /* NAN(SNAN) */, 0x7FF0000000000001ull /* NAN(SNAN) */ },
{ 0x7FF7FFFFFFFFFFFFull /* NAN(SNAN) */, 0x7FF7FFFFFFFFFFFFull /* NAN(SNAN) */ },
#else
{ 0x7FF0000000000001ull /* NAN(SNAN) */, 0x7FF8000000000001ull /* NAN */ },
{ 0x7FF7FFFFFFFFFFFFull /* NAN(SNAN) */, 0x7FFFFFFFFFFFFFFFull /* NAN */ },
#endif
{ 0x7FF8000000000000ull /* NAN */, 0x7FF8000000000000ull /* NAN */ },
{ 0x7FF8000000000001ull /* NAN */, 0x7FF8000000000001ull /* NAN */ },
{ 0x7FFFFFFFFFFFFFFFull /* NAN */, 0x7FFFFFFFFFFFFFFFull /* NAN */ },
{ 0xFFF0000000000000ull /* -INF */, 0x7FF0000000000000ull /* INF */ },
#ifdef _M_AMD64
{ 0xFFF0000000000001ull /* -NAN(SNAN) */, 0xFFF0000000000001ull /* NAN(SNAN) */ },
{ 0xFFF7FFFFFFFFFFFFull /* -NAN(SNAN) */, 0xFFF7FFFFFFFFFFFFull /* NAN(SNAN) */ },
#else
{ 0xFFF0000000000001ull /* -NAN(SNAN) */, 0xFFF8000000000001ull /* -NAN */ },
{ 0xFFF7FFFFFFFFFFFFull /* -NAN(SNAN) */, 0xFFFFFFFFFFFFFFFFull /* -NAN */ },
#endif
{ 0xFFF8000000000000ull /* -NAN(IND) */, 0xFFF8000000000000ull /* -NAN(IND) */ },
{ 0xFFF8000000000001ull /* -NAN */, 0xFFF8000000000001ull /* -NAN */ },
{ 0xFFFFFFFFFFFFFFFFull /* -NAN */, 0xFFFFFFFFFFFFFFFFull /* -NAN */ },
/* Some random floats */
{ 0x0000000000000000 /* 0.000000000000000e+000 */, 0x0000000000000000 /* 0.000000000000000e+000 */ },
{ 0x8000000000000000 /* -0.000000000000000e+000 */, 0x0000000000000000 /* 0.000000000000000e+000 */ },
{ 0x0123456789abcdef /* 3.512700564088504e-303 */, 0x0123456789abcdef /* 3.512700564088504e-303 */ },
{ 0x8123456789abcdef /* -3.512700564088504e-303 */, 0x0123456789abcdef /* 3.512700564088504e-303 */ },
{ 0x472ad8b31f506c9e /* 6.969745516432332e+034 */, 0x472ad8b31f506c9e /* 6.969745516432332e+034 */ },
{ 0xc72ad8b31f506c9e /* -6.969745516432332e+034 */, 0x472ad8b31f506c9e /* 6.969745516432332e+034 */ },
{ 0x1d289e506fa47cb3 /* 3.261613668384938e-168 */, 0x1d289e506fa47cb3 /* 3.261613668384938e-168 */ },
{ 0x9d289e506fa47cb3 /* -3.261613668384938e-168 */, 0x1d289e506fa47cb3 /* 3.261613668384938e-168 */ },
};
void Test_fabs(void)
{
int i;
for (i = 0; i < _countof(s_fabs_tests); i++)
{
double x = u64_to_dbl(s_fabs_tests[i].x);
double z = fabs(x);
ok_eq_dbl_exact("fabs", s_fabs_tests[i].x, z, s_fabs_tests[i].result);
}
}
static TESTENTRY_FLT s_fabsf_tests[] =
{
/* Special values */
{ 0x7F800000 /* INF */, 0x7F800000 /* INF */ },
{ 0x7F800001 /* NAN(SNAN) */, 0x7FC00001 /* NAN */ },
{ 0x7FBFFFFF /* NAN(SNAN) */, 0x7FFFFFFF /* NAN */ },
{ 0x7FC00000 /* NAN */, 0x7FC00000 /* NAN */ },
{ 0x7FC00001 /* NAN */, 0x7FC00001 /* NAN */ },
{ 0x7FCFFFFF /* NAN */, 0x7FCFFFFF /* NAN */ },
{ 0xFF800000 /* -INF */, 0x7F800000 /* INF */ },
{ 0xFF800001 /* -NAN(SNAN) */, 0xFFC00001 /* -NAN */ },
{ 0xFFBFFFFF /* -NAN(SNAN) */, 0xFFFFFFFF /* -NAN */ },
{ 0xFFC00000 /* -NAN(IND) */, 0xFFC00000 /* -NAN */ },
{ 0xFFC00001 /* -NAN */, 0xFFC00001 /* -NAN */ },
{ 0xFFCFFFFF /* -NAN */, 0xFFCFFFFF /* -NAN */ },
/* Some random floats */
{ 0x00000000 /* 0.000000e+000 */, 0x00000000 /* 0.000000e+000 */ },
{ 0x80000000 /* -0.000000e+000 */, 0x00000000 /* 0.000000e+000 */ },
{ 0x01234567 /* 2.998817e-038 */, 0x01234567 /* 2.998817e-038 */ },
{ 0x81234567 /* -2.998817e-038 */, 0x01234567 /* 2.998817e-038 */ },
{ 0x472ad8b3 /* 4.373670e+004 */, 0x472ad8b3 /* 4.373670e+004 */ },
{ 0xc72ad8b3 /* -4.373670e+004 */, 0x472ad8b3 /* 4.373670e+004 */ },
{ 0x1d289e50 /* 2.231646e-021 */, 0x1d289e50 /* 2.231646e-021 */ },
{ 0x9d289e50 /* -2.231646e-021 */, 0x1d289e50 /* 2.231646e-021 */ },
};
void Test_fabsf(void)
{
int i;
for (i = 0; i < _countof(s_fabsf_tests); i++)
{
float x = u32_to_flt(s_fabsf_tests[i].x);
float z = fabsf(x);
ok_eq_flt_exact("fabsf", s_fabsf_tests[i].x, z, s_fabsf_tests[i].result);
}
}
START_TEST(fabs)
{
Test_fabs();
Test_fabsf();
}

View file

@ -0,0 +1,77 @@
/*
* PROJECT: ReactOS api tests
* LICENSE: MIT (https://spdx.org/licenses/MIT)
* PURPOSE: Helpers for testing math functions
* COPYRIGHT: Copyright 2021 Timo Kreuzer <timo.kreuzer@reactos.org>
*/
#pragma once
#define _USE_MATH_DEFINES
#include <math.h>
#include <float.h>
#include <apitest.h>
static
__inline
double
u64_to_dbl(UINT64 x)
{
return *(double*)(&x);
}
static
__inline
UINT64
dbl_to_u64(double x)
{
return *(UINT64*)(&x);
}
static
__inline
float
u32_to_flt(UINT32 x)
{
return *(float*)(&x);
}
static
__inline
UINT32
flt_to_u32(float x)
{
return *(UINT32*)(&x);
}
typedef struct _TESTENTRY_DBL
{
unsigned long long x;
unsigned long long result;
} TESTENTRY_DBL;
typedef struct _TESTENTRY_FLT
{
unsigned long x;
unsigned long result;
} TESTENTRY_FLT;
#define ok_eq_dbl_exact_(file, line, func, ullx, z, ullexp) \
{ \
double x = u64_to_dbl(ullx); \
unsigned long long ullz = dbl_to_u64(z); \
double exp = u64_to_dbl(ullexp); \
ok_(file, line)(ullz == ullexp, "Wrong value for '%s(%f)' [0x%016llx], expected: %f [0x%016llx], got: %f [0x%016llx]\n", \
func, x, ullx, exp, ullexp, z, ullz); \
}
#define ok_eq_dbl_exact(func, ullx, z, ullexp) ok_eq_dbl_exact_(__FILE__, __LINE__, func, ullx, z, ullexp)
#define ok_eq_flt_exact_(file, line, func, ux, z, uexp) \
{ \
float x = u32_to_flt(ux); \
unsigned int uz = flt_to_u32(z); \
float exp = u32_to_flt(uexp); \
ok_(file, line)(uz == uexp, "Wrong value for '%s(%f)' [0x%08x], expected: %f [0x%08x], got: %f [0x%08x]\n", \
func, x, ux, exp, uexp, z, uz); \
}
#define ok_eq_flt_exact(func, ux, z, uexp) ok_eq_flt_exact_(__FILE__, __LINE__, func, ux, z, uexp)

View file

@ -1033,7 +1033,7 @@ list(APPEND SOURCE_MSVCRT
# div.c
# exit.c
# exp.c
# fabs.c
fabs.c
# fclose.c
# feof.c
# ferror.c
@ -1404,6 +1404,10 @@ set_module_type(msvcrt_crt_apitest win32cui)
add_importlibs(msvcrt_crt_apitest msvcrt kernel32 ntdll)
add_rostests_file(TARGET msvcrt_crt_apitest)
if(CMAKE_C_COMPILER_ID STREQUAL "GNU")
target_compile_options(msvcrt_crt_apitest PRIVATE -Wno-format)
endif()
spec2def(msvcrt_crt_dll_startup.dll dll_startup.spec)
add_library(msvcrt_crt_dll_startup MODULE
dll_startup.cpp

View file

@ -7,6 +7,7 @@ list(APPEND SOURCE_STATIC
_vsnprintf.c
_vsnwprintf.c
atexit.c
fabs.c
mbstowcs.c
mbtowc.c
sprintf.c
@ -40,3 +41,7 @@ target_link_libraries(static_crt_apitest crt wine ${PSEH_LIB})
set_module_type(static_crt_apitest win32cui)
add_importlibs(static_crt_apitest kernel32 ntdll)
add_rostests_file(TARGET static_crt_apitest)
if(CMAKE_C_COMPILER_ID STREQUAL "GNU")
target_compile_options(static_crt_apitest PRIVATE -Wno-format)
endif()

View file

@ -18,6 +18,7 @@ extern void func___64tof(void);
#if defined(TEST_NTDLL)
extern void func__vscwprintf(void);
#endif
extern void func_fabs(void);
extern void func_fputc(void);
extern void func_fputwc(void);
extern void func__snprintf(void);
@ -60,6 +61,7 @@ const struct test winetest_testlist[] =
// ...
#endif
#if defined(TEST_STATIC_CRT) || defined(TEST_MSVCRT)
{ "fabs", func_fabs },
#if defined(_M_ARM)
{ "__rt_div", func___rt_div },
{ "__fto64", func___fto64 },

View file

@ -169,7 +169,9 @@ _Check_return_ __CRT_INLINE float __CRTDECL ldexpf(_In_ float x, _In_ int y) { r
_Check_return_ __CRT_INLINE long double __CRTDECL tanl(_In_ long double x) { return (tan((double)x)); }
#endif
#if defined(__ia64__) || defined(_M_IA64) || \
#if defined(_CRTBLD)
_Check_return_ float __cdecl fabsf(_In_ float x);
#elif defined(__ia64__) || defined(_M_IA64) || \
defined(__arm__) || defined(_M_ARM) || \
defined(__arm64__) || defined(_M_ARM64)
_Check_return_ _CRT_JIT_INTRINSIC _CRTIMP float __cdecl fabsf(_In_ float x);