[CRT:MATH] Import nextafter, nextafterf and nexttowardf from musl

Note: On Windows, where a long double is the same as a double, nextafterl is the same as nextafter, nexttowardl is the same as nexttoward.
Also nexttoward is the same as nextafter.
This commit is contained in:
Timo Kreuzer 2024-11-20 16:23:22 +02:00
parent 5c26ccdb29
commit a9ee20cb9a
12 changed files with 210 additions and 39 deletions

View file

@ -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)

View file

@ -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)

View file

@ -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)

View file

@ -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)

View file

@ -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

View file

@ -6,7 +6,6 @@ list(APPEND CRT_FLOAT_SOURCE
float/copysign.c
float/fpclass.c
float/fpecode.c
float/nafter.c
float/scalb.c
)

View file

@ -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 <precomp.h>
/*
* @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;
}

70
sdk/lib/crt/math/libm.h Normal file
View file

@ -0,0 +1,70 @@
//
// libm.h
//
// Partly imported from musl libc
//
// Support header for musl math code.
//
// SPDX-License-Identifier: MIT
//
#pragma once
#include <stdint.h>
#include <float.h>
#include <math.h>
// 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)

View file

@ -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

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}