54318: mathfunc: add isnan() and isinf(). also document NaN + Inf

This commit is contained in:
dana
2026-04-13 11:04:58 -05:00
parent 08e48ea8b6
commit bfb982d682
7 changed files with 59 additions and 3 deletions

View File

@@ -1,5 +1,10 @@
2026-04-13 dana <dana@dana.is>
* 54318: Doc/Zsh/arith.yo, Doc/Zsh/mod_mathfunc.yo,
Functions/Misc/zmathfuncdef, NEWS, Src/Modules/mathfunc.c,
Test/V03mathfunc.ztst: mathfunc: add isnan() and isinf(). also
document NaN + Inf
* 54313: README, Src/params.c, Test/B02typeset.ztst: convfloat:
use consistent capitalisation for NaN, Inf, and -Inf

View File

@@ -122,6 +122,33 @@ taken for a parameter name. All numeric parts (before and after the
decimal point and in the exponent) may contain underscores after the
leading digit for visual guidance; these are ignored in computation.
The special floating point values NaN (not a number) and infinity are
fully supported in floating point arithmetic. They may be produced by
certain operations, such as division by zero, or referenced explicitly in
arithmetic constructs and float assignments using the case-insensitive
constants tt(NaN) and tt(Inf). Expansion syntax must be used to
reference a parameter with one of these names in these contexts:
example(% nan=123 INF=456
% print $LPAR()LPAR() nan RPAR()RPAR() $LPAR()LPAR() INF RPAR()RPAR()
NaN Inf
% print $LPAR()LPAR() $nan RPAR()RPAR() $LPAR()LPAR() $INF RPAR()RPAR()
123 456
% typeset -F f=nan && typeset -p f
typeset -F f=NaN
% typeset -F f=$nan && typeset -p f
typeset -F f=123.0000000000)
To check whether a value is NaN, either use the tt(isnan) function
provided by the tt(zsh/mathfunc) module
or compare it to the string tt(NaN):
example(% zmodload zsh/mathfunc
% (( isnan(0.0 / 0) )) && print is nan
is nan
% typeset -F f=nan && [[ $f == NaN ]] && print is nan
is nan)
cindex(arithmetic operators)
cindex(operators, arithmetic)
An arithmetic expression uses nearly the same syntax and

View File

@@ -27,8 +27,8 @@ tt(floor), tt(gamma), tt(j0), tt(j1), tt(lgamma), tt(log), tt(log10),
tt(log1p), tt(log2), tt(logb), tt(sin), tt(sinh), tt(sqrt), tt(tan),
tt(tanh), tt(y0), tt(y1). The tt(atan) function can optionally take a
second argument, in which case it behaves like the C function tt(atan2).
The tt(ilogb) function takes a single floating point argument, but
returns an integer.
The tt(ilogb), tt(isinf), and tt(isnan) functions take a single floating
point argument, but return an integer.
The function tt(signgam) takes no arguments, and returns an integer, which
is the C variable of the same name, as described in manref(gamma)(3). Note

View File

@@ -61,7 +61,7 @@ if ! zmodload -e zsh/mathfunc; then
mathfuncs=(abs acos acosh asin asinh atan atanh cbrt ceil cos cosh erf erfc
exp expm1 fabs float floor gamma int j0 j1 lgamma log log10 log1p logb
sin sinh sqrt tan tanh y0 y1 signgam copysign fmod hypot nextafter jn yn
ldexp scalb rand48)
ldexp scalb rand48 ilogb isinf isnan log2 rint)
mathfuncpat="(${(j.|.)mathfuncs})"
bodysearch=$body
while [[ $bodysearch = (#b)(*[^[:alnum]]|)([[:alnum:]]##)\((*) ]]; do

2
NEWS
View File

@@ -72,6 +72,8 @@ The new completion helper _shadow can be used to temporarily wrap or
substitute a function. The contrib function mkshadow makes it easier
to use outside of completion contexts.
The zsh/mathfunc module now provides isnan() and isinf() functions.
Changes since 5.8.1
-------------------

View File

@@ -57,6 +57,8 @@ MF_GAMMA,
MF_HYPOT,
MF_ILOGB,
MF_INT,
MF_ISINF,
MF_ISNAN,
MF_J0,
MF_J1,
MF_JN,
@@ -135,6 +137,8 @@ static struct mathfunc mftab[] = {
NUMMATHFUNC("hypot", math_func, 2, 2, MF_HYPOT),
NUMMATHFUNC("ilogb", math_func, 1, 1, MF_ILOGB | TFLAG(TF_NOASS)),
NUMMATHFUNC("int", math_func, 1, 1, MF_INT | TFLAG(TF_NOASS)),
NUMMATHFUNC("isinf", math_func, 1, 1, MF_ISINF | TFLAG(TF_NOASS)),
NUMMATHFUNC("isnan", math_func, 1, 1, MF_ISNAN | TFLAG(TF_NOASS)),
NUMMATHFUNC("j0", math_func, 1, 1, MF_J0),
NUMMATHFUNC("j1", math_func, 1, 1, MF_J1),
NUMMATHFUNC("jn", math_func, 2, 2, MF_JN | TFLAG(TF_INT1)),
@@ -308,6 +312,16 @@ math_func(UNUSED(char *name), int argc, mnumber *argv, int id)
ret.u.l = (zlong)argd;
break;
case MF_ISINF:
ret.type = MN_INTEGER;
ret.u.l = (zlong) isinf(argd);
break;
case MF_ISNAN:
ret.type = MN_INTEGER;
ret.u.l = (zlong) isnan(argd);
break;
case MF_J0:
retd = j0(argd);
break;

View File

@@ -145,3 +145,11 @@ F:This test fails if your math library doesn't have erand48().
print -r - "$a, $b, $c"
0:log2
>-1.00000, 0.58496, 6.62936
() {
local -F n=nan i1=inf i2=-inf
(( isnan(Nan) && isinf(Inf) && isinf(-Inf) )) &&
(( isnan(n) && isinf(i1) && isinf(i2) )) &&
(( !isnan(Inf) && !isinf(NaN) ))
}
0:isinf, isnan