summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordana <dana@dana.is>2026-04-13 11:04:58 -0500
committerdana <dana@dana.is>2026-04-13 11:07:56 -0500
commitbfb982d6824a41ebff1fc5934ebee7f01df1e682 (patch)
tree4cf710d17dcd411e88f1f5261ed96ec15202c394
parent54313: convfloat: use consistent capitalisation for NaN, Inf, and -Inf (diff)
downloadzsh-bfb982d6824a41ebff1fc5934ebee7f01df1e682.tar
zsh-bfb982d6824a41ebff1fc5934ebee7f01df1e682.tar.gz
zsh-bfb982d6824a41ebff1fc5934ebee7f01df1e682.tar.bz2
zsh-bfb982d6824a41ebff1fc5934ebee7f01df1e682.tar.lz
zsh-bfb982d6824a41ebff1fc5934ebee7f01df1e682.tar.xz
zsh-bfb982d6824a41ebff1fc5934ebee7f01df1e682.tar.zst
zsh-bfb982d6824a41ebff1fc5934ebee7f01df1e682.zip
54318: mathfunc: add isnan() and isinf(). also document NaN + Inf
-rw-r--r--ChangeLog5
-rw-r--r--Doc/Zsh/arith.yo27
-rw-r--r--Doc/Zsh/mod_mathfunc.yo4
-rw-r--r--Functions/Misc/zmathfuncdef2
-rw-r--r--NEWS2
-rw-r--r--Src/Modules/mathfunc.c14
-rw-r--r--Test/V03mathfunc.ztst8
7 files changed, 59 insertions, 3 deletions
diff --git a/ChangeLog b/ChangeLog
index d57d30b41..c532eeb4e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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
diff --git a/Doc/Zsh/arith.yo b/Doc/Zsh/arith.yo
index f8807eb4a..17eb3cc36 100644
--- a/Doc/Zsh/arith.yo
+++ b/Doc/Zsh/arith.yo
@@ -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
diff --git a/Doc/Zsh/mod_mathfunc.yo b/Doc/Zsh/mod_mathfunc.yo
index 61aa3decf..b7223e2cf 100644
--- a/Doc/Zsh/mod_mathfunc.yo
+++ b/Doc/Zsh/mod_mathfunc.yo
@@ -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
diff --git a/Functions/Misc/zmathfuncdef b/Functions/Misc/zmathfuncdef
index 5ed991f68..6b8dfe1dd 100644
--- a/Functions/Misc/zmathfuncdef
+++ b/Functions/Misc/zmathfuncdef
@@ -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
diff --git a/NEWS b/NEWS
index 4b26c0b03..7509eb0df 100644
--- a/NEWS
+++ b/NEWS
@@ -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
-------------------
diff --git a/Src/Modules/mathfunc.c b/Src/Modules/mathfunc.c
index fc2593dca..0941b3bb1 100644
--- a/Src/Modules/mathfunc.c
+++ b/Src/Modules/mathfunc.c
@@ -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;
diff --git a/Test/V03mathfunc.ztst b/Test/V03mathfunc.ztst
index 9a297d69d..8380b5c41 100644
--- a/Test/V03mathfunc.ztst
+++ b/Test/V03mathfunc.ztst
@@ -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