diff --git a/dll/win32/crtdll/crtdll.spec b/dll/win32/crtdll/crtdll.spec index c8b9da5e884..09fca4d3cc2 100644 --- a/dll/win32/crtdll/crtdll.spec +++ b/dll/win32/crtdll/crtdll.spec @@ -236,7 +236,7 @@ @ cdecl _mkdir(str) @ cdecl _mktemp(str) @ cdecl _msize(ptr) -@ cdecl _nextafter(double double) +@ cdecl _nextafter(double double) nextafter @ cdecl _onexit(ptr) @ varargs _open(str long) @ cdecl _open_osfhandle(long long) diff --git a/dll/win32/msvcrt/msvcrt.spec b/dll/win32/msvcrt/msvcrt.spec index f0ec4ea34a5..15334fcf92d 100644 --- a/dll/win32/msvcrt/msvcrt.spec +++ b/dll/win32/msvcrt/msvcrt.spec @@ -882,8 +882,8 @@ @ cdecl _mktime64(ptr) @ cdecl _msize(ptr) @ stub -version=0x600+ -arch=i386 _msize_debug -@ cdecl _nextafter(double double) -@ stub -arch=x86_64 _nextafterf +@ cdecl _nextafter(double double) nextafter +@ cdecl -arch=!i386 _nextafterf(long) nextafterf @ extern _onexit # Declaring it as extern let us use the symbol from msvcrtex while having the __imp_ symbol defined in the import lib @ varargs _open(str long) @ cdecl _open_osfhandle(long long) diff --git a/dll/win32/msvcrt20/msvcrt20.spec b/dll/win32/msvcrt20/msvcrt20.spec index 0e499d055a1..2d15a360855 100644 --- a/dll/win32/msvcrt20/msvcrt20.spec +++ b/dll/win32/msvcrt20/msvcrt20.spec @@ -739,7 +739,7 @@ @ cdecl _msize(ptr) @ stub _mtlock @ stub _mtunlock -@ cdecl _nextafter(double double) +@ cdecl _nextafter(double double) nextafter @ cdecl _onexit(ptr) @ varargs _open(str long) @ cdecl _open_osfhandle(long long) diff --git a/dll/win32/msvcrt40/msvcrt40.spec b/dll/win32/msvcrt40/msvcrt40.spec index 6e005a3f85d..08a8332815d 100644 --- a/dll/win32/msvcrt40/msvcrt40.spec +++ b/dll/win32/msvcrt40/msvcrt40.spec @@ -800,7 +800,7 @@ @ cdecl _msize(ptr) @ stub _mtlock @ stub _mtunlock -@ cdecl _nextafter(double double) +@ cdecl _nextafter(double double) nextafter @ cdecl _onexit(ptr) @ varargs _open(str long) @ cdecl _open_osfhandle(long long) diff --git a/dll/win32/ucrtbase/ucrtbase.spec b/dll/win32/ucrtbase/ucrtbase.spec index 731b8118f89..e2ed7928125 100644 --- a/dll/win32/ucrtbase/ucrtbase.spec +++ b/dll/win32/ucrtbase/ucrtbase.spec @@ -1792,9 +1792,9 @@ @ cdecl _o_nextafter(double double) nextafter @ cdecl _o_nextafterf(float float) nextafterf @ cdecl _o_nextafterl(double double) nextafter -@ cdecl _o_nexttoward(double double) nexttoward +@ cdecl _o_nexttoward(double double) nextafter @ cdecl _o_nexttowardf(float double) nexttowardf -@ cdecl _o_nexttowardl(double double) nexttoward +@ cdecl _o_nexttowardl(double double) nextafter @ cdecl _o_pow(double double) pow @ cdecl -arch=!i386 _o_powf(float float) powf @ cdecl _o_putc(long ptr) putc @@ -2511,12 +2511,12 @@ @ cdecl -stub nearbyint(double) @ cdecl -stub nearbyintf(float) @ cdecl nearbyintl(double) nearbyint -@ cdecl -stub nextafter(double double) -@ cdecl -stub nextafterf(float float) +@ cdecl nextafter(double double) +@ cdecl nextafterf(float float) @ cdecl nextafterl(double double) nextafter -@ cdecl -stub nexttoward(double double) nexttoward -@ cdecl -stub nexttowardf(float double) nexttowardf -@ cdecl nexttowardl(double double) nexttoward +@ cdecl nexttoward(double double) nextafter +@ cdecl nexttowardf(float double) +@ cdecl nexttowardl(double double) nextafter @ stub norm @ stub normf @ stub norml diff --git a/sdk/lib/crt/float/float.cmake b/sdk/lib/crt/float/float.cmake index 036dfa3e3f9..4fcea518309 100644 --- a/sdk/lib/crt/float/float.cmake +++ b/sdk/lib/crt/float/float.cmake @@ -6,7 +6,6 @@ list(APPEND CRT_FLOAT_SOURCE float/copysign.c float/fpclass.c float/fpecode.c - float/nafter.c float/scalb.c ) diff --git a/sdk/lib/crt/float/nafter.c b/sdk/lib/crt/float/nafter.c deleted file mode 100644 index 23115769b53..00000000000 --- a/sdk/lib/crt/float/nafter.c +++ /dev/null @@ -1,26 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS system libraries - * FILE: lib/sdk/crt/float/nafter.c - * PURPOSE: Unknown - * PROGRAMER: Unknown - * UPDATE HISTORY: - * 25/11/05: Added license header - */ - -#include - -/* - * @implemented - */ -double _nextafter( double x, double y ) -{ - WARN("This function is not implemented correctly\n"); - if ( x == y) - return x; - - if ( _isnan(x) || _isnan(y) ) - return x; - - return x; -} diff --git a/sdk/lib/crt/math/libm.h b/sdk/lib/crt/math/libm.h new file mode 100644 index 00000000000..b29a065d2e9 --- /dev/null +++ b/sdk/lib/crt/math/libm.h @@ -0,0 +1,70 @@ +// +// libm.h +// +// Partly imported from musl libc +// +// Support header for musl math code. +// +// SPDX-License-Identifier: MIT +// + +#pragma once + +#include +#include +#include + +// Define _STATIC_ASSERT for compatibility with legacy CRT headers +#ifndef _STATIC_ASSERT +#define _STATIC_ASSERT(expr) extern char (*__static_assert__(void)) [(expr) ? 1 : -1] +#endif + +// Make sure the sizes are correct +_STATIC_ASSERT(sizeof(float) == 4); +_STATIC_ASSERT(sizeof(double) == 8); +_STATIC_ASSERT(sizeof(long double) == 8); + +_Check_return_ int __cdecl _isnanf(_In_ float _X); +#define isnan _isnan +#define isnanf _isnanf + +// musl has this in math.h +static __inline uint32_t __FLOAT_BITS(float __f) +{ + union {float __f; uint32_t __i;} __u; + __u.__f = __f; + return __u.__i; +} + +static __inline uint64_t __DOUBLE_BITS(double __f) +{ + union {double __f; uint64_t __i;} __u; + __u.__f = __f; + return __u.__i; +} + +#define signbit(x) \ + ((sizeof(x) == sizeof(float)) ? (int)(__FLOAT_BITS(x)>>31) : \ + (int)(__DOUBLE_BITS(x)>>63)) + +static inline void fp_force_evalf(float x) +{ + volatile float y; + y = x; + (void)y; +} + +static inline void fp_force_eval(double x) +{ + volatile double y; + y = x; + (void)y; +} + +#define FORCE_EVAL(x) do { \ + if (sizeof(x) == sizeof(float)) { \ + fp_force_evalf(x); \ + } else { \ + fp_force_eval(x); \ + } \ +} while(0) diff --git a/sdk/lib/crt/math/math.cmake b/sdk/lib/crt/math/math.cmake index 5e42eb26d13..305f4b97528 100644 --- a/sdk/lib/crt/math/math.cmake +++ b/sdk/lib/crt/math/math.cmake @@ -14,6 +14,9 @@ list(APPEND LIBCNTPR_MATH_SOURCE math/div.c math/exp2f.c math/labs.c + math/nextafter.c + math/nextafterf.c + math/nexttowardf.c math/round.c math/roundf.c math/scalbn.c diff --git a/sdk/lib/crt/math/nextafter.c b/sdk/lib/crt/math/nextafter.c new file mode 100644 index 00000000000..d97ff8f737a --- /dev/null +++ b/sdk/lib/crt/math/nextafter.c @@ -0,0 +1,41 @@ +/* + * PROJECT: ReactOS CRT + * LICENSE: MIT (https://spdx.org/licenses/MIT) + * PURPOSE: Implementation of nextafter. + * COPYRIGHT: Imported from musl libc + * https://git.musl-libc.org/cgit/musl/tree/src/math/nextafter.c + * blob: ab5795a47a93e36c8c461d8a4be6621b582ae077 + * See https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT + */ + +#include "libm.h" + +double nextafter(double x, double y) +{ + union {double f; uint64_t i;} ux={x}, uy={y}; + uint64_t ax, ay; + int e; + + if (isnan(x) || isnan(y)) + return x + y; + if (ux.i == uy.i) + return y; + ax = ux.i & ~0ULL/2; + ay = uy.i & ~0ULL/2; + if (ax == 0) { + if (ay == 0) + return y; + ux.i = (uy.i & 1ULL<<63) | 1; + } else if (ax > ay || ((ux.i ^ uy.i) & 1ULL<<63)) + ux.i--; + else + ux.i++; + e = ux.i >> 52 & 0x7ff; + /* raise overflow if ux.f is infinite and x is finite */ + if (e == 0x7ff) + FORCE_EVAL(x+x); + /* raise underflow if ux.f is subnormal or zero */ + if (e == 0) + FORCE_EVAL(x*x + ux.f*ux.f); + return ux.f; +} diff --git a/sdk/lib/crt/math/nextafterf.c b/sdk/lib/crt/math/nextafterf.c new file mode 100644 index 00000000000..c5ba95bb4da --- /dev/null +++ b/sdk/lib/crt/math/nextafterf.c @@ -0,0 +1,40 @@ +/* + * PROJECT: ReactOS CRT + * LICENSE: MIT (https://spdx.org/licenses/MIT) + * PURPOSE: Implementation of nextafterf. + * COPYRIGHT: Imported from musl libc + * https://git.musl-libc.org/cgit/musl/tree/src/math/nextafterf.c + * blob: 75a09f7d1cf115d9a5d5dfeda9b12d42de269904 + * See https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT + */ + +#include "libm.h" + +float nextafterf(float x, float y) +{ + union {float f; uint32_t i;} ux={x}, uy={y}; + uint32_t ax, ay, e; + + if (isnanf(x) || isnanf(y)) + return x + y; + if (ux.i == uy.i) + return y; + ax = ux.i & 0x7fffffff; + ay = uy.i & 0x7fffffff; + if (ax == 0) { + if (ay == 0) + return y; + ux.i = (uy.i & 0x80000000) | 1; + } else if (ax > ay || ((ux.i ^ uy.i) & 0x80000000)) + ux.i--; + else + ux.i++; + e = ux.i & 0x7f800000; + /* raise overflow if ux.f is infinite and x is finite */ + if (e == 0x7f800000) + FORCE_EVAL(x+x); + /* raise underflow if ux.f is subnormal or zero */ + if (e == 0) + FORCE_EVAL(x*x + ux.f*ux.f); + return ux.f; +} diff --git a/sdk/lib/crt/math/nexttowardf.c b/sdk/lib/crt/math/nexttowardf.c new file mode 100644 index 00000000000..482393cebce --- /dev/null +++ b/sdk/lib/crt/math/nexttowardf.c @@ -0,0 +1,44 @@ +/* + * PROJECT: ReactOS CRT + * LICENSE: MIT (https://spdx.org/licenses/MIT) + * PURPOSE: Implementation of scalbn. + * COPYRIGHT: Imported from musl nexttowardf + * https://git.musl-libc.org/cgit/musl/tree/src/math/nexttowardf.c + * blob: bbf172f9e65573e9059d26ea574aa8a96dfdef43 + */ + +#include "libm.h" + +float nexttowardf(float x, long double y) +{ + union {float f; uint32_t i;} ux = {x}; + uint32_t e; + + if (_isnan(x) || _isnan(y)) + return x + y; + if (x == y) + return y; + if (x == 0) { + ux.i = 1; + if (signbit(y)) + ux.i |= 0x80000000; + } else if (x < y) { + if (signbit(x)) + ux.i--; + else + ux.i++; + } else { + if (signbit(x)) + ux.i++; + else + ux.i--; + } + e = ux.i & 0x7f800000; + /* raise overflow if ux.f is infinite and x is finite */ + if (e == 0x7f800000) + FORCE_EVAL(x+x); + /* raise underflow if ux.f is subnormal or zero */ + if (e == 0) + FORCE_EVAL(x*x + ux.f*ux.f); + return ux.f; +}