Files
vlibc/include/math.h
T

635 lines
16 KiB
C

#ifndef VLIBC_MATH_H
#define VLIBC_MATH_H
/*
* vlibc — <math.h>.
*
* This header is ISO C core and is present in every profile. It carries the
* whole todo-39 arithmetic inventory: the classification macros
* (fpclassify/isnan/isinf/isfinite/isnormal/signbit), the constants
* (HUGE_VAL/INFINITY/NAN, FP_*, math_errhandling), and the 25 basic
* real-function families (fabs, copysign, floor, ceil, trunc, round, rint,
* nearbyint, lrint, llrint, frexp, ldexp, modf, scalbn, scalbln, fmin,
* fmax, fdim, fmod, remainder, remquo, ilogb, logb, lround, llround), each
* spelled in all three precisions (float `...f`, double, long double
* `...l`).
*
* Every declaration below lands NOW so that the header is stable across the
* todo-39 implementation slices; the slices (wip commits) fill in the
* src/math/ definitions family by family and never touch this header again.
* Later math todos extend this header in place the same way stdlib.h is
* extended: todo 40 adds the exp/log/pow families, todo 41 the trig and
* hyperbolic families, todo 42 erf/erfc/lgamma/tgamma/fma/nextafter/nan,
* and todo 43 provides <complex.h> separately.
*
* Edge-case behavior (IEEE 754-2008): floor/ceil/trunc round exact results
* with correct signed-zero and NaN/Inf handling; fabs/copysign/fmin/fmax/
* fdim never raise an exception on their own and preserve NaN payloads
* where the standard allows; the classification macros are
* exception-free. Functions that per POSIX can set errno (ldexp, scalbn,
* scalbln, fmod, remainder, remquo, and the fraction-splitters frexp/modf
* with their pointer outputs) carry no const attribute below so the
* compiler never hoists or elides an errno-setting call. Functions that
* are pure (never set errno in their defined domain — fabs, copysign,
* floor, ceil, trunc, round, rint, nearbyint, fmin, fmax, fdim, ilogb,
* logb) are declared const and fold away in static links.
*/
#include <vlibc/features.h>
#include <limits.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
/* ---- Constants ---- */
/*
* Positive infinity, as double/float/long double (C23 7.12.1p4). HUGE_VAL
* is also the "overflowed" return value of the strto* conversions.
*/
#define HUGE_VAL __builtin_huge_val()
#define HUGE_VALF __builtin_huge_valf()
#define HUGE_VALL __builtin_huge_vall()
/* Positive infinity as a float (C23 7.12.1p5). */
#define INFINITY __builtin_inff()
/* A quiet NaN as a float (C23 7.12.1p6); the payload is implementation
* defined but always a NaN of the quiet kind. */
#define NAN __builtin_nanf("")
/*
* Return values of fpclassify (C23 7.12.3.1): the numbers need only be
* distinct positive values; the classification macros below hand these
* exact constants to __builtin_fpclassify so the two always agree.
*/
#define FP_NAN 0
#define FP_INFINITE 1
#define FP_ZERO 2
#define FP_SUBNORMAL 3
#define FP_NORMAL 4
/*
* Return values of ilogb (C23 7.12.6.5p4): FP_ILOGB0 for a zero argument
* and FP_ILOGBNAN for a NaN or infinite argument, each the indicated
* <limits.h> sentinel.
*/
#define FP_ILOGB0 INT_MIN
#define FP_ILOGBNAN INT_MAX
/*
* Which error mechanisms the library reports through (C23 7.12.1p3):
* MATH_ERRNO and MATH_ERREXCEPT are both in effect (the domain/range
* errno values are set where POSIX requires and the corresponding
* floating-point exceptions are raised by the hardware).
*/
#define MATH_ERRNO 1
#define MATH_ERREXCEPT 2
#define math_errhandling 3
/* ---- Classification macros (type-generic, exception-free) ---- */
/*
* Classify x as NaN, infinite, zero, subnormal, or normal, returning the
* matching FP_* constant. __builtin_fpclassify is a GCC type-generic
* builtin that evaluates its floating argument exactly once and never
* traps, so no _Generic dispatch is needed here.
*/
#define fpclassify(x) \
__builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO, (x))
/*
* The predicate macros below are thin wrappers over the corresponding
* GCC type-generic builtins. Each builtin evaluates its argument once and
* returns an int; integer arguments classify as finite, non-zero, and
* normal (they convert exactly), so isnan(3) is 0 and isinf(3) is 0.
*/
#define isnan(x) __builtin_isnan(x)
#define isinf(x) __builtin_isinf(x)
#define isfinite(x) __builtin_isfinite(x)
#define isnormal(x) __builtin_isnormal(x)
#define signbit(x) __builtin_signbit(x)
/* ---- Basic arithmetic families (todo 39) ---- */
/*
* Absolute value of x (C23 7.12.7.2). fabs(±0) is +0, fabs(±Inf) is +Inf,
* and fabs(NaN) is a NaN. Pure: no domain, no exception.
*/
__attribute__((const)) float
fabsf(float x);
__attribute__((const)) double
fabs(double x);
__attribute__((const)) long double
fabsl(long double x);
/*
* A value with the magnitude of x and the sign of y (C23 7.12.7.3).
* copysign(±0, y) carries y's sign; a NaN x keeps its payload but takes
* y's sign bit. Pure.
*/
__attribute__((const)) float
copysignf(float x, float y);
__attribute__((const)) double
copysign(double x, double y);
__attribute__((const)) long double
copysignl(long double x, long double y);
/*
* The largest integral value not greater than x (C23 7.12.9.2).
* floor(±0) is ±0, floor(-0.5) is -1.0, floor(±Inf) and floor(NaN)
* return their argument unchanged. Pure and exact (no inexact
* exception), so it folds.
*/
__attribute__((const)) float
floorf(float x);
__attribute__((const)) double
floor(double x);
__attribute__((const)) long double
floorl(long double x);
/*
* The smallest integral value not less than x (C23 7.12.9.1).
* ceil(±0) is ±0, ceil(-0.5) is -0.0 (a real negative zero), ceil(±Inf)
* and ceil(NaN) return their argument unchanged. Pure and exact.
*/
__attribute__((const)) float
ceilf(float x);
__attribute__((const)) double
ceil(double x);
__attribute__((const)) long double
ceill(long double x);
/*
* The integral value nearest to x in the direction of zero (C23 7.12.9.3).
* trunc(-0.7) is -0.0, trunc(0.7) is 0.0, and ±Inf/NaN pass through.
* Pure and exact.
*/
__attribute__((const)) float
truncf(float x);
__attribute__((const)) double
trunc(double x);
__attribute__((const)) long double
truncl(long double x);
/*
* The integral value nearest to x, with halfway cases rounded away from
* zero (C23 7.12.9.6). round(±0) is ±0, round(-0.5) is -1.0, and ±Inf/
* NaN pass through. Pure: round never raises the inexact exception.
*/
__attribute__((const)) float
roundf(float x);
__attribute__((const)) double
round(double x);
__attribute__((const)) long double
roundl(long double x);
/*
* The integral value nearest to x in the current rounding direction
* (C23 7.12.9.4). rint may raise the inexact exception; it is still pure
* in the const sense because it never sets errno and reads no memory.
*/
__attribute__((const)) float
rintf(float x);
__attribute__((const)) double
rint(double x);
__attribute__((const)) long double
rintl(long double x);
/*
* As rint, but guaranteed never to raise the inexact exception (C23
* 7.12.9.5). Pure and exact.
*/
__attribute__((const)) float
nearbyintf(float x);
__attribute__((const)) double
nearbyint(double x);
__attribute__((const)) long double
nearbyintl(long double x);
/*
* The nearest integral value to x in the current rounding direction,
* returned as long (C23 7.12.9.7). A result outside the range of long is
* a range error (the return value is unspecified and errno may be set),
* so no const attribute.
*/
long
lrintf(float x);
long
lrint(double x);
long
lrintl(long double x);
/*
* As lrint, returned as long long (C23 7.12.9.8). Range errors as for
* lrint; no const attribute.
*/
long long
llrintf(float x);
long long
llrint(double x);
long long
llrintl(long double x);
/*
* Split x into a fraction f in [1/2, 1) (or 0) and an integer exponent
* *exp such that x == f * 2^(*exp) (C23 7.12.6.4). Zero returns ±0 with
* *exp 0; Inf/NaN return x with an unspecified *exp. Writes *exp, so no
* const attribute.
*/
float
frexpf(float x, int *exp);
double
frexp(double x, int *exp);
long double
frexpl(long double x, int *exp);
/*
* x times 2^n (C23 7.12.6.3): the inverse of frexp. A result too large
* to represent is a range error returning ±HUGE_VAL with errno ERANGE;
* no const attribute.
*/
float
ldexpf(float x, int n);
double
ldexp(double x, int n);
long double
ldexpl(long double x, int n);
/*
* Split x into an integral part stored in *iptr and a fractional part
* returned (C23 7.12.6.5); both have x's sign, so modf(-1.5, &i) puts
* -1.0 in i and returns -0.5. Writes *iptr, so no const attribute.
*/
float
modff(float x, float *iptr);
double
modf(double x, double *iptr);
long double
modfl(long double x, long double *iptr);
/*
* x * FLT_RADIX^n with FLT_RADIX 2 (C23 7.12.6.6): the scalb* functions
* differ from ldexp only in the exponent argument's type. A result too
* large to represent is a range error returning ±HUGE_VAL* with errno
* ERANGE; no const attribute.
*/
float
scalbnf(float x, int n);
double
scalbn(double x, int n);
long double
scalbnl(long double x, int n);
float
scalblnf(float x, long n);
double
scalbln(double x, long n);
long double
scalblnl(long double x, long n);
/*
* The smaller of x and y (C23 7.12.12.4), returning -0.0 when the
* arguments are +0.0 and -0.0. A NaN argument is ignored in favor of the
* numeric one; two NaNs return a NaN. Pure.
*/
__attribute__((const)) float
fminf(float x, float y);
__attribute__((const)) double
fmin(double x, double y);
__attribute__((const)) long double
fminl(long double x, long double y);
/*
* The larger of x and y (C23 7.12.12.3), returning +0.0 when the
* arguments are +0.0 and -0.0. NaN handling as fmin. Pure.
*/
__attribute__((const)) float
fmaxf(float x, float y);
__attribute__((const)) double
fmax(double x, double y);
__attribute__((const)) long double
fmaxl(long double x, long double y);
/*
* The positive difference x - y when x > y and +0.0 otherwise (C23
* 7.12.12.2); fdim(x, NaN) and fdim(NaN, x) return a NaN. Pure in the
* domain-error-free sense (an overflow may still raise an exception
* through the hardware, which const does not model).
*/
__attribute__((const)) float
fdimf(float x, float y);
__attribute__((const)) double
fdim(double x, double y);
__attribute__((const)) long double
fdiml(long double x, long double y);
/*
* The floating-point remainder x - n*y, where n is x/y truncated toward
* zero (C23 7.12.10.1); the result therefore has x's sign. fmod(x, ±0) is
* a domain error returning NaN with errno EDOM; ±Inf/x is likewise a
* domain error. errno can be set, so no const attribute.
*/
float
fmodf(float x, float y);
double
fmod(double x, double y);
long double
fmodl(long double x, long double y);
/*
* The IEEE remainder x - n*y, where n is x/y rounded to the nearest
* integer (ties to even) (C23 7.12.10.2); |result| <= |y|/2. Domain
* errors as fmod; errno can be set, so no const attribute.
*/
float
remainderf(float x, float y);
double
remainder(double x, double y);
long double
remainderl(long double x, long double y);
/*
* As remainder, additionally storing the low bits of the integer
* quotient n in *quo (C23 7.12.10.3). Writes *quo, so no const
* attribute.
*/
float
remquof(float x, float y, int *quo);
double
remquo(double x, double y, int *quo);
long double
remquol(long double x, long double y, int *quo);
/*
* The signed exponent of x as an int (C23 7.12.6.5p1): ilogb(x) is
* floor(log2 |x|) for a nonzero finite x. ilogb(±0) returns FP_ILOGB0,
* ilogb(±Inf) and ilogb(NaN) return FP_ILOGBNAN. Pure: the sentinels are
* returned without touching errno.
*/
__attribute__((const)) int
ilogbf(float x);
__attribute__((const)) int
ilogb(double x);
__attribute__((const)) int
ilogbl(long double x);
/*
* The signed exponent of x as a floating-point value (C23 7.12.6.6):
* logb(±0) is -Inf and logb(±Inf) is +Inf, each raising the division-
* by-zero/invalid exception through the hardware but without an errno
* path in the representable domain. Pure.
*/
__attribute__((const)) float
logbf(float x);
__attribute__((const)) double
logb(double x);
__attribute__((const)) long double
logbl(long double x);
/*
* The nearest integral value to x, with halfway cases rounded away from
* zero, returned as long (C23 7.12.9.9). A result outside the range of
* long is a range error; no const attribute.
*/
long
lroundf(float x);
long
lround(double x);
long
lroundl(long double x);
/*
* As lround, returned as long long (C23 7.12.9.10). Range errors as for
* lround; no const attribute.
*/
long long
llroundf(float x);
long long
llround(double x);
long long
llroundl(long double x);
/*
* e raised to the power x (C23 7.12.6.1). exp(+0) == exp(-0) == 1;
* exp(-Inf) == +0; exp(+Inf) == +Inf; exp(NaN) == NaN. A result too
* large or too small is a range error and sets errno to ERANGE, so no
* const attribute.
*/
double
exp(double x);
float
expf(float x);
long double
expl(long double x);
/*
* 2 raised to the power x (C23 7.12.6.2). exp2(+0) == exp2(-0) == 1;
* exp2(-Inf) == +0; exp2(+Inf) == +Inf; exp2(NaN) == NaN. A result too
* large or too small is a range error and sets errno to ERANGE, so no
* const attribute.
*/
double
exp2(double x);
float
exp2f(float x);
long double
exp2l(long double x);
/*
* e raised to the power x minus 1 (C23 7.12.6.3). expm1(+0) == +0;
* expm1(-0) == -0; expm1(-Inf) == -1; expm1(+Inf) == +Inf;
* expm1(NaN) == NaN. A result too large is a range error and sets
* errno to ERANGE, so no const attribute.
*/
double
expm1(double x);
float
expm1f(float x);
long double
expm1l(long double x);
/*
* Natural logarithm of x (C23 7.12.6.7). log(+0) == log(-0) == -Inf;
* log(1) == 0; log(-x) == NaN (domain error); log(+Inf) == +Inf;
* log(NaN) == NaN. A negative argument is a domain error setting errno
* to EDOM and a zero argument is a range error setting errno to ERANGE,
* so no const attribute.
*/
double
log(double x);
float
logf(float x);
long double
logl(long double x);
/*
* Base-2 logarithm of x (C23 7.12.6.8). log2(1) == 0; log2(2) == 1.
* Special values, domain errors, and range errors as for log, so no
* const attribute.
*/
double
log2(double x);
float
log2f(float x);
long double
log2l(long double x);
/*
* Base-10 logarithm of x (C23 7.12.6.9). log10(1) == 0; log10(10) == 1.
* Special values, domain errors, and range errors as for log, so no
* const attribute.
*/
double
log10(double x);
float
log10f(float x);
long double
log10l(long double x);
/*
* Natural logarithm of 1 + x (C23 7.12.6.13). log1p(+-0) == +-0;
* log1p(-1) == -Inf (a pole error setting errno to ERANGE); log1p(x) for
* x < -1 is a domain error setting errno to EDOM; log1p(+Inf) == +Inf;
* log1p(NaN) == NaN. Accurate for x close to 0, so no const attribute.
*/
double
log1p(double x);
float
log1pf(float x);
long double
log1pl(long double x);
/*
* Principal square root of x (C23 7.12.5.4). sqrt(+-0) == +-0; sqrt(x)
* for x < 0 is a domain error returning NaN and setting errno to EDOM;
* sqrt(+Inf) == +Inf; sqrt(NaN) == NaN. Correctly rounded; no const
* attribute because of the errno path.
*/
double
sqrt(double x);
float
sqrtf(float x);
long double
sqrtl(long double x);
/*
* Cube root of x (C23 7.12.5.5). cbrt(+-0) == +-0; cbrt(+-Inf) == +-Inf;
* cbrt(NaN) == NaN; cbrt(-x) == -cbrt(x). Defined for all reals and never
* sets errno.
*/
double
cbrt(double x);
float
cbrtf(float x);
long double
cbrtl(long double x);
/*
* Square root of x*x + y*y without undue overflow or underflow
* (C23 7.12.5.6). hypot(+-0, +-0) == +0; hypot(+-Inf, y) == +Inf even for
* NaN y; hypot(x, NaN) == NaN for finite x. The internal scaling avoids
* spurious overflow, so no errno path exists.
*/
double
hypot(double x, double y);
float
hypotf(float x, float y);
long double
hypotl(long double x, long double y);
/*
* x raised to the power y (C23 7.12.6.11). pow(x, 0) == 1; pow(1, y) == 1
* even for NaN y; pow(NaN, 0) == 1; pow(+-0, negative y) == +-Inf (a pole
* error setting errno to ERANGE); pow(negative finite x, non-integer y) is
* a domain error setting errno to EDOM; overflow and underflow set errno to
* ERANGE. No const attribute.
*/
double
pow(double x, double y);
float
powf(float x, float y);
long double
powl(long double x, long double y);
#ifdef __cplusplus
}
#endif
#endif /* VLIBC_MATH_H */