Ksh93 has unexpected, undocumented, support for math functions


I have been thinking about whether I want to contribute to the maintenance of the Korn shell (ksh93) since it was open sourced in 2013. While trying to understand the organization of the project and how to build it I noticed that the math builtin (e.g., $(( ... )) ) supports a lot of functions I was not aware of despite having used the Korn shell for more than two decades. Consider these examples:

$ echo $(( nearbyint(12.5) ))
12
$ echo $(( round(12.5) ))
13
$ echo $(( rint(12.5) ))
12

Why in the world should a command line shell support multiple methods to round a floating point value to an integer? There are numerous other examples of that type and they all derive from the ksh authors thinking that exposing low-level APIs to a shell script was appropriate.

These functions are defined in src/cmd/ksh93/data/math.tab. None are documented outside of the source code other than a pro-forma mention in the documentation that they exist (see the section labeled “Arithmetic Evaluation” in the man page) as prefaced by this text:

Any of the following math library functions that are in the C math library can be used within an arithmetic expression:

These are the functions in that table:

# <return type: i:integer f:floating-point> [<typed -arg-bitmask> < #floating-point-args> <function -name> [
# </function><function -name>l and </function><function -name>f variants are handled by features/math.sh
# @(#)math.tab (AT&T Research) 2013-08-11
f 1 acos
f 1 acosh
f 1 asin
f 1 asinh
f 1 atan
f 2 atan2
f 1 atanh
f 1 cbrt
f 1 ceil
f 2 copysign
f 1 cos
f 1 cosh
f 1 erf
f 1 erfc
f 1 exp
f 1 exp10
f 1 exp2
f 1 expm1
f 1 fabs abs
f 2 fdim
i 1 finite
f 1 float
f 1 floor
f 3 fma
f 2 fmax
f 2 fmin
f 2 fmod
i 1 fpclassify
i 1 fpclass
f 2 hypot
i 1 ilogb
f 1 int
i 1 isfinite
i 2 isgreater
i 2 isgreaterequal
i 1 isinf
i 1 isinfinite
i 2 isless
i 2 islessequal
i 2 islessgreater
i 1 isnan
i 1 isnormal
i 1 issubnormal fpclassify=FP_SUBNORMAL
i 2 isunordered
i 1 iszero fpclassify=FP_ZERO fpclass=FP_NZERO|FP_PZERO {return a1==0.0||a1==-0.0;} j0
f 1 j1
f 2 jn
x 2 ldexp
f 1 lgamma
f 1 log
f 1 log10
f 1 log1p
f 1 log2
f 1 logb
f 1 nearbyint
f 1 2 nextafter
f 1 2 nexttoward
f 2 pow
f 2 remainder
f 1 rint
f 1 round {Sfdouble_t r;Sflong_t y;y=floor(2*a1);r=rint(a1);if(2*a1==y)r+=(r<a1 )-(a1<0);return r;}
f 2 scalb
f 2 scalbn
i 1 signbit
f 1 sin
f 1 sinh
f 1 sqrt
f 1 tan
f 1 tanh
f 1 tgamma {Sfdouble_t r=exp(lgamma(a1));return (signgam<0)?-r:r;}
f 1 trunc
f 1 y0
f 1 y1
f 2 yn

The only way I would contribute to the evolution of ksh93 is if this bogosity were eliminated. There is no reason that a CLI like ksh/ksh93 should support all of those math functions. In fact most of those functions have no business being available in a CLI. Consider what it means to execute $(( isfinite(1) )). In the context of a CLI shell script the isifinite() function has no meaning.