Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: return status of the 'let' builtin



On Wed 8 Apr 2026, at 00:32, Jun T wrote:
> In workers/42369 (16 Feb. 2018):
>     "zsh/mathfunc should provide an isnan() function"
> but there is no isnan() yet. Should we add it now?

yes i like that, below adds isnan() + isinf() and updates the docs to
reflect the `typeset -p` change and address your feedback

obv documenting it like this means we'll be committing to the
capitalisation 'NaN' for convfloat()

dana


diff --git a/Doc/Zsh/arith.yo b/Doc/Zsh/arith.yo
index 9f5298821..6e5aaa8aa 100644
--- a/Doc/Zsh/arith.yo
+++ b/Doc/Zsh/arith.yo
@@ -120,6 +120,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/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




Messages sorted by: Reverse Date, Date, Thread, Author