diff --git a/native/lib/xl.math.xl b/native/lib/xl.math.xl index 357a90a9f..db15bb554 100644 --- a/native/lib/xl.math.xl +++ b/native/lib/xl.math.xl @@ -34,34 +34,89 @@ // If not, see . // ***************************************************************************** -MATH is -// ---------------------------------------------------------------------------- -// Implementation of the math module -// ---------------------------------------------------------------------------- +with + X:real + Y:real + Z:real + N:natural + I:integer + Base:real - // Basic math functions - abs X:integer as integer is builtin IAbs - abs X:real as real is builtin FAbs - sqrt X:real as real is C sqrt +// Generic implementation of abs and sign +generic_abs T is (if T < 0 then -T else T) +generic_sign T is (if T < 0 then -1 else if T > 0 then 1 else 0) - sin X:real as real is C sin - cos X:real as real is C cos - tan X:real as real is C tan - asin X:real as real is C asin - acos X:real as real is C acos - atan X:real as real is C atan - atan Y:real, X:real as real is C atan2 +abs I as integer is generic_abs I +sign I as integer is generic_sign I +abs X as real is generic_abs X +sign X as real is generic_sign X - sinh X:real as real is C sinh - cosh X:real as real is C cosh - tanh X:real as real is C tanh - asinh X:real as real is C asinh - acosh X:real as real is C acosh - atanh X:real as real is C atanh +// Nearest integer +ceil X as real is C "ceil" +floor X as real is C "floor" - exp X:real as real is C exp - expm1 X:real as real is C expm1 - log X:real as real is C log - log10 X:real as real is C log10 - log2 X:real as real is C log2 - log1p X:real as real is C log1p +// C interface for base functions +sqrt X as real is C "sqrt" +exp X as real is C "exp" +exp2 X as real is C "exp2" +log X as real is C "log" +ln X as real is log X +log10 X as real is C "log10" +log2 X as real is C "log2" +logb X as integer is C "logb" +log(Base,X) as real is (log X / log Base) +hypot(X,Y) as real is C "hypot" +cbrt X as real is C "cbrt" +erf X as real is C "erf" +lgamma X as real is C "lgamma" +fma X,Y,Z as real is C "fma" + +// Circular trigonometry +sin X as real is C "sin" +cos X as real is C "cos" +tan X as real is C "tan" +asin X as real is C "asin" +acos X as real is C "acos" +atan X as real is C "atan" +atan Y/X as real is C "atan2" + +// Hyperbolic trigonometry +sinh X as real is C "sinh" +cosh X as real is C "cosh" +tanh X as real is C "tanh" +asinh X as real is C "asinh" +acosh X as real is C "acosh" +atanh X as real is C "atanh" + +// Bessel functions +j0 X as real is C "j0" +j1 X as real is C "j1" +jn I, X as real is C "jn" +y0 X as real is C "y0" +y1 X as real is C "y1" +yn I, X as real is C "yn" + +// Optimized forms +(exp X)-1.0 as real is C "expm1" +log (1.0+X) as real is C "log1p" +log (X+1.0) as real is C "log1p" +2.0^X as real is C "exp2" + +// Constants +pi is 3.1415926535897932384626433 +e is 2.7182818284590452353602875 + +// Optimized expressions +// constant (log2 [[e]]) is 1.442695040888963407359924681001892137 +// constant (log10 [[e]]) is 0.434294481903251827651128918916605082 +// constant (log 2.0) is 0.693147180559945309417232121458176568 +// constant (pi/2.0) is 1.570796326794896619231321691639751442 +// constant (pi/4.0) is 0.785398163397448309615660845819875721 +// constant (pi*0.5) is constant(pi/2.0) +// constant (pi*0.25) is constant(pi/4.0) +// constant (1.0/[[pi]]) is 0.318309886183790671537767526745028724 +// constant (2.0/[[pi]]) is 0.636619772367581343075535053490057448 +// constant (2.0/sqrt [[pi]]) is 1.128379167095512573896158903121545172 +// constant (sqrt 2.0) is 1.414213562373095048801688724209698079 +// constant (1.0/sqrt 2.0) is 0.707106781186547524400844362104849039 +// constant (sqrt 2.0/2.0) is 0.707106781186547524400844362104849039 diff --git a/native/lib/xl.math.xs b/native/lib/xl.math.xs index 4f92c17ea..4413c9e61 100644 --- a/native/lib/xl.math.xs +++ b/native/lib/xl.math.xs @@ -34,64 +34,99 @@ // If not, see . // ***************************************************************************** -module ARBITRARY_PRECISION +with + X:real + Y:real + Z:real + N:natural + I:integer + Base:real -module COMPLEX -module QUATERNION -module VECTOR -module MATRIX -module STATISTICS +// Functions on integer values +abs I as integer +sign I as integer +// Functions on real values +abs X as real +sign X as real +ceil X as real +floor X as real +sqrt X as real +exp X as real +exp2 X as real +log X as real +ln X as real +log10 X as real +log2 X as real +logb X as integer +log(Base,X) as real +hypot(X,Y) as real +hypothenuse(X,Y)as real is hypot(X,Y) +cbrt X as real +CubeRoot X as real is cbrt X +erf X as real +ErrorFunction X as real is erf X +lgamma X as real +LogGamma X as real is lgamma X +fma X,Y,Z as real +X*Y+Z as real is fma X,Y,Z +Z+X*Y as real is fma X,Y,Z -// Using the `MATH` module by default uses `real` functions and constants -use REAL -use MATH[real].FUNCTIONS -use MATH[real].CONSTANTS +// Circular trigonometry +sin X as real +cos X as real +tan X as real +asin X as real +acos X as real +atan X as real +atan Y/X as real +// Hyperbolic trigonometry +sinh X as real +cosh X as real +tanh X as real +asinh X as real +acosh X as real +atanh X as real -module MATH[type number] with -// ---------------------------------------------------------------------------- -// Interface of the math module for a given number type -// ---------------------------------------------------------------------------- +// Bessel functions +j0 X as real +j1 X as real +jn I, X as real +J 0, X as real is j0 X +J 1, X as real is j1 X +J I, X as real is jn I,X +y0 X as real +y1 X as real +yn I, X as real +Y 0, X as real is y0 X +Y 1, X as real is y1 X +Y I, X as real is yn I, X - module FUNCTIONS with - // ------------------------------------------------------------------------ - // Interface for basic math functions - // ------------------------------------------------------------------------ +// Optimized forms +(exp X) - 1.0 as real +log (1.0+X) as real +log (X+1.0) as real +2.0^X as real - Abs X:number as number - Sign X:number as integer - Sqrt X:number as number +// Constants +pi +e - Sin X:number as number - Cos X:number as number - Tan X:number as number - ArcSin X:number as number - ArcCos X:number as number - ArcTan X:number as number - ArcTan Y:number, X:number as number - - SinH X:number as number - CosH X:number as number - TanH X:number as number - ArcSinH X:number as number - ArcCosH X:number as number - ArcTanH X:number as number - - Exp X:number as number - Exp X:number - 1 as number - Log X:number as number - Log10 X:number as number - Log2 X:number as number - Log2i X:number as integer - Log (1 + X:number) as number - - - module CONSTANTS is - // ------------------------------------------------------------------------ - // Interface for math constants - // ------------------------------------------------------------------------ - ZERO is number 0 - ONE is number 1 - TWO is number 2 - PI is number 3.1415926535897932384626433 +// Optimized expressions +// constant (log2 [[e]]) +// constant (log10 [[e]]) +// constant (log 2.0) +// constant (pi/2.0) +// constant (pi/4.0) +// constant (pi*0.5) +// constant (pi*0.25) +// constant (1.0/[[pi]]) +// constant (2.0/[[pi]]) +// constant (2.0/sqrt [[pi]]) +// constant (1.0/[[pi]]) +// constant (2.0/[[pi]]) +// constant (2.0/sqrt [[pi]]) +// constant (sqrt 2.0) +// constant (1.0/sqrt 2.0) +// constant (sqrt 2.0/2.0) diff --git a/src/builtins.xl b/src/builtins.xl index 8ec6de8e1..ba549b507 100644 --- a/src/builtins.xl +++ b/src/builtins.xl @@ -150,23 +150,8 @@ Source:text from First:natural as text is text_range(Source, First, not 0) parse Source:text is C "xl_parse_text" // Basic math functions -abs X is if X < 0 then -X else X -pi is 3.1415926535897932384626433 -sin X:real as real is C "sin" -cos X:real as real is C "cos" -tan X:real as real is C "tan" -asin X:real as real is C "asin" -acos X:real as real is C "acos" -atan X:real as real is C "atan" -exp X:real as real is C "exp" -exp2 X:real as real is C "exp2" -expm1 X:real as real is C "expm1" -log X:real as real is C "log" -log2 X:real as real is C "log2" -log10 X:real as real is C "log10" -log1p X:real as real is C "log1p" -sqrt X:real as real is C "sqrt" -atan Y:real / X:real as real is C "atan2" +abs X is if X < 0 then -X else X +sign X is if X < 0 then -1 else if X > 0 then 1 else 0 // If-then-else statement if [[true]] then True else False is True diff --git a/src/posix.cpp b/src/posix.cpp index 6b121e519..e2772d240 100644 --- a/src/posix.cpp +++ b/src/posix.cpp @@ -71,21 +71,62 @@ double fn(double x, double y) \ NATIVE(fn); \ } -MATH(sin); -MATH(cos); -MATH(tan); -MATH(asin); -MATH(acos); -MATH(atan); +#define MATH2I(fn) \ +namespace \ +{ \ +double fn(int x, double y) \ +{ \ + return ::fn(x, y); \ +} \ +NATIVE(fn); \ +} + +#define MATH3(fn) \ +namespace \ +{ \ +double fn(double x, double y, double z) \ +{ \ + return ::fn(x, y, z); \ +} \ +NATIVE(fn); \ +} + +MATH(ceil); +MATH(floor); +MATH(sqrt); MATH(exp); -MATH(expm1); MATH(exp2); +MATH(expm1); MATH(log); MATH(log2); MATH(log10); MATH(log1p); -MATH(sqrt); -MATH2(atan2); +MATH(logb); +MATH2(hypot); +MATH(cbrt); +MATH(erf); +MATH(lgamma); +MATH3(fma); MATH2(pow); +MATH(sin); +MATH(cos); +MATH(tan); +MATH(asin); +MATH(acos); +MATH(atan); +MATH2(atan2); +MATH(sinh); +MATH(cosh); +MATH(tanh); +MATH(asinh); +MATH(acosh); +MATH(atanh); +MATH(j0); +MATH(j1); +MATH2I(jn); +MATH(y0); +MATH(y1); +MATH2I(yn); + XL_END diff --git a/tests/01.Evaluation/04-write-types.xl b/tests/01.Evaluation/04-write-types.xl index d61592355..494b3a3cd 100644 --- a/tests/01.Evaluation/04-write-types.xl +++ b/tests/01.Evaluation/04-write-types.xl @@ -31,6 +31,8 @@ // along with XL, in a file named COPYING. // If not, see . // ***************************************************************************** +import XL.MATH + print "Hello" print 'C' print 12 diff --git a/tests/01.Evaluation/bug3327.ref b/tests/01.Evaluation/bug3327.ref index 8cb66c37c..aff798cf2 100644 --- a/tests/01.Evaluation/bug3327.ref +++ b/tests/01.Evaluation/bug3327.ref @@ -1 +1 @@ -23.1407 +8.53973 diff --git a/tests/01.Evaluation/bug3327.xl b/tests/01.Evaluation/bug3327.xl index 9658b468d..1ee1d96ee 100644 --- a/tests/01.Evaluation/bug3327.xl +++ b/tests/01.Evaluation/bug3327.xl @@ -31,4 +31,6 @@ // along with XL, in a file named COPYING. // If not, see . // ***************************************************************************** -exp(1) * pi +import XL.MATH + +pi * exp(1) diff --git a/tests/02.Arithmetic/07-math-functions.ref b/tests/02.Arithmetic/07-math-functions.ref index 079515cf6..cad95f896 100644 --- a/tests/02.Arithmetic/07-math-functions.ref +++ b/tests/02.Arithmetic/07-math-functions.ref @@ -1,61 +1,181 @@ +--- Running tests with 1.13331e-07 --- +abs 1.13331e-07=1.13331e-07 +sign 1.13331e-07=1 +ceil 1.13331e-07=1 +floor 1.13331e-07=0 +sqrt 1.13331e-07=0.000336647 +exp 1.13331e-07=1 +exp2 1.13331e-07=1 +expm1 1.13331e-07=1.13331e-07 +log 1.13331e-07=-15.993 +log10 1.13331e-07=-6.94565=-6.94565 +log2 1.13331e-07=-23.073 +log1p 1.13331e-07=1.13331e-07=1.13331e-07 +hypot 1.13331e-07=1=1 +cbrt 1.13331e-07=0.0048393=0.0048393 +erf 1.13331e-07=1.2788e-07=1.2788e-07 +lgamma 1.13331e-07=15.993=15.993 +fma 1.13331e-07=2=2 +0.25+sin 1.13331e-07=0.25 +0.25+cos 1.13331e-07=1.25 +0.25+tan 1.13331e-07=0.25 +asin 1.13331e-07=1.13331e-07 +acos 1.13331e-07=1.5708 +atan 1.13331e-07=1.13331e-07 +0.25+sinh 1.13331e-07=0.25 +0.25+cosh 1.13331e-07=1.25 +0.25+tanh 1.13331e-07=0.25 +asinh 1.13331e-07=1.13331e-07 +acosh 1.13331e-07=nan +atanh 1.13331e-07=1.13331e-07 +j0 1.13331e-07=1=1 +j1 1.13331e-07=5.66655e-08=5.66655e-08 +j3 1.13331e-07=3.03253e-23=3.03253e-23 +y0 1.13331e-07=-10.2552=-10.2552 +y1 1.13331e-07=-5.61735e+06=-5.61735e+06 +y3 1.13331e-07=-3.49884e+21=-3.49884e+21 --- Running tests with 0.13331 --- abs 0.13331=0.13331 +sign 0.13331=1 +ceil 0.13331=1 +floor 0.13331=0 sqrt 0.13331=0.365116 -sin 0.13331=0.382915 -cos 0.13331=1.24113 -tan 0.13331=0.384105 -asin 0.13331=0.133708 -acos 0.13331=1.43709 -atan 0.13331=0.132529 exp 0.13331=1.1426 +exp2 0.13331=1.09681 expm1 0.13331=0.142604 log 0.13331=-2.01508 -log10 0.13331=-0.875137 +log10 0.13331=-0.875137=-0.875137 log2 0.13331=-2.90714 -log1p 0.13331=0.125143 +log1p 0.13331=0.125143=0.125143 +hypot 0.13331=1.14112=1.14112 +cbrt 0.13331=0.510843=0.510843 +erf 0.13331=0.149538=0.149538 +lgamma 0.13331=1.95187=1.95187 +fma 0.13331=2.28439=2.28439 +0.25+sin 0.13331=0.382915 +0.25+cos 0.13331=1.24113 +0.25+tan 0.13331=0.384105 +asin 0.13331=0.133708 +acos 0.13331=1.43709 +atan 0.13331=0.132529 +0.25+sinh 0.13331=0.383705 +0.25+cosh 0.13331=1.2589 +0.25+tanh 0.13331=0.382526 +asinh 0.13331=0.132918 +acosh 0.13331=nan +atanh 0.13331=0.134108 +j0 0.13331=0.995562=0.995562 +j1 0.13331=0.066507=0.066507 +j3 0.13331=4.9302e-05=4.9302e-05 +y0 0.13331=-1.3478=-1.3478 +y1 0.13331=-4.88681=-4.88681 +y3 0.13331=-2154.51=-2154.51 --- Running tests with 1.3331 --- abs 1.3331=1.3331 +sign 1.3331=1 +ceil 1.3331=2 +floor 1.3331=1 sqrt 1.3331=1.1546 -sin 1.3331=1.22188 -cos 1.3331=0.485464 -tan 1.3331=4.37752 -asin 1.3331=nan -acos 1.3331=nan -atan 1.3331=0.927211 exp 1.3331=3.79278 +exp2 1.3331=2.51943 expm1 1.3331=2.79278 log 1.3331=0.287507 -log10 1.3331=0.124863 +log10 1.3331=0.124863=0.124863 log2 1.3331=0.414785 -log1p 1.3331=0.847198 +log1p 1.3331=0.847198=0.847198 +hypot 1.3331=2.6871=2.6871 +cbrt 1.3331=1.10058=1.10058 +erf 1.3331=0.940609=0.940609 +lgamma 1.3331=-0.113161=-0.113161 +fma 1.3331=6.44336=6.44336 +0.25+sin 1.3331=1.22188 +0.25+cos 1.3331=0.485464 +0.25+tan 1.3331=4.37752 +asin 1.3331=nan +acos 1.3331=nan +atan 1.3331=0.927211 +0.25+sinh 1.3331=2.01456 +0.25+cosh 1.3331=2.27822 +0.25+tanh 1.3331=1.12 +asinh 1.3331=1.09847 +acosh 1.3331=0.795101 +atanh 1.3331=nan +j0 1.3331=0.60269=0.60269 +j1 1.3331=0.529047=0.529047 +j3 1.3331=0.0441123=0.0441123 +y0 1.3331=0.304305=0.304305 +y1 1.3331=-0.52524=-0.52524 +y3 1.3331=-2.75224=-2.75224 --- Running tests with 3.14159 --- abs 3.14159=3.14159 +sign 3.14159=1 +ceil 3.14159=4 +floor 3.14159=3 sqrt 3.14159=1.77245 -sin 3.14159=0.25 -cos 3.14159=-0.75 -tan 3.14159=0.25 -asin 3.14159=nan -acos 3.14159=nan -atan 3.14159=1.26263 exp 3.14159=23.1407 +exp2 3.14159=8.82498 expm1 3.14159=22.1407 log 3.14159=1.14473 -log10 3.14159=0.49715 +log10 3.14159=0.49715=0.49715 log2 3.14159=1.6515 -log1p 3.14159=1.42108 +log1p 3.14159=1.42108=1.42108 +hypot 3.14159=5.19831=5.19831 +cbrt 3.14159=1.46459=1.46459 +erf 3.14159=0.999991=0.999991 +lgamma 3.14159=0.827695=0.827695 +fma 3.14159=18.1528=18.1528 +0.25+sin 3.14159=0.25 +0.25+cos 3.14159=-0.75 +0.25+tan 3.14159=0.25 +asin 3.14159=nan +acos 3.14159=nan +atan 3.14159=1.26263 +0.25+sinh 3.14159=11.7987 +0.25+cosh 3.14159=11.842 +0.25+tanh 3.14159=1.24627 +asinh 3.14159=1.8623 +acosh 3.14159=1.81153 +atanh 3.14159=nan +j0 3.14159=-0.304242=-0.304242 +j1 3.14159=0.284615=0.284615 +j3 3.14159=0.333458=0.333458 +y0 3.14159=0.328366=0.328366 +y1 3.14159=0.358873=0.358873 +y3 3.14159=-0.48607=-0.48607 --- Running tests with 6.28319 --- abs 6.28319=6.28319 +sign 6.28319=1 +ceil 6.28319=7 +floor 6.28319=6 sqrt 6.28319=2.50663 -sin 6.28319=0.25 -cos 6.28319=1.25 -tan 6.28319=0.25 -asin 6.28319=nan -acos 6.28319=nan -atan 6.28319=1.41297 exp 6.28319=535.492 +exp2 6.28319=77.8802 expm1 6.28319=534.492 log 6.28319=1.83788 -log10 6.28319=0.79818 +log10 6.28319=0.79818=0.79818 log2 6.28319=2.6515 -log1p 6.28319=1.98557 +log1p 6.28319=1.98557=1.98557 +hypot 6.28319=9.6189=9.6189 +cbrt 6.28319=1.84527=1.84527 +erf 6.28319=1=1 +lgamma 6.28319=5.27779=5.27779 +fma 6.28319=54.0448=54.0448 +0.25+sin 6.28319=0.25 +0.25+cos 6.28319=1.25 +0.25+tan 6.28319=0.25 +asin 6.28319=nan +acos 6.28319=nan +atan 6.28319=1.41297 +0.25+sinh 6.28319=267.995 +0.25+cosh 6.28319=267.997 +0.25+tanh 6.28319=1.24999 +asinh 6.28319=2.5373 +acosh 6.28319=2.52463 +atanh 6.28319=nan +j0 6.28319=0.220277=0.220277 +j1 6.28319=-0.212383=-0.212383 +j3 6.28319=0.0291122=0.0291122 +y0 6.28319=-0.229109=-0.229109 +y1 6.28319=-0.239074=-0.239074 +y3 6.28319=0.336483=0.336483 true diff --git a/tests/02.Arithmetic/07-math-functions.xl b/tests/02.Arithmetic/07-math-functions.xl index e7a972941..e5cfad679 100644 --- a/tests/02.Arithmetic/07-math-functions.xl +++ b/tests/02.Arithmetic/07-math-functions.xl @@ -31,25 +31,58 @@ // along with XL, in a file named COPYING. // If not, see . // ***************************************************************************** + +import XL.MATH + run_test x is print "--- Running tests with ", x, " ---" print "abs ", x, "=", abs x + print "sign ", x, "=", sign x + + print "ceil ", x, "=", ceil x + print "floor ", x, "=", floor x print "sqrt ", x, "=", sqrt x - // Avoid platform-dependent rounding errors for very small values - print "sin ", x, "=", 0.25 + sin x - print "cos ", x, "=", 0.25 + cos x - print "tan ", x, "=", 0.25 + tan x - print "asin ", x, "=", asin x - print "acos ", x, "=", acos x - print "atan ", x, "=", atan x + print "exp ", x, "=", exp x - print "expm1 ", x, "=", expm1 x + print "exp2 ", x, "=", exp2 x + print "expm1 ", x, "=", exp x - 1 print "log ", x, "=", log x - print "log10 ", x, "=", log10 x + print "log10 ", x, "=", log10 x, "=", log(10,x) print "log2 ", x, "=", log2 x - print "log1p ", x, "=", log1p x + print "log1p ", x, "=", log(1+x), "=", log(x+1) + + print "hypot ", x, "=", hypot(x, x+1), "=", hypothenuse(x, x+1) + print "cbrt ", x, "=", cbrt(x), "=", CubeRoot(x) + print "erf ", x, "=", erf(x), "=", ErrorFunction(x) + print "lgamma ", x, "=", lgamma(x), "=", LogGamma(x) + print "fma ", x, "=", fma(x, x+1, x+2), "=", x * (x+1) + (x+2) + + // Trig functions - Avoid platform-dependent rounding for small values + print "0.25+sin ", x, "=", 0.25 + sin x + print "0.25+cos ", x, "=", 0.25 + cos x + print "0.25+tan ", x, "=", 0.25 + tan x + print "asin ", x, "=", asin x + print "acos ", x, "=", acos x + print "atan ", x, "=", atan x + + // Hyperbolic functions + print "0.25+sinh ", x, "=", 0.25 + sinh x + print "0.25+cosh ", x, "=", 0.25 + cosh x + print "0.25+tanh ", x, "=", 0.25 + tanh x + print "asinh ", x, "=", asinh x + print "acosh ", x, "=", acosh x + print "atanh ", x, "=", atanh x + + // Bessel functions + print "j0 ", x, "=", j0(x), "=", j(0,x) + print "j1 ", x, "=", j1(x), "=", j(1,x) + print "j3 ", x, "=", jn(3, x), "=", j(3, x) + print "y0 ", x, "=", y0(x), "=", y(0,x) + print "y1 ", x, "=", y1(x), "=", y(1,x) + print "y3 ", x, "=", yn(3, x), "=", y(3, x) +run_test 1.13331e-7 run_test 0.13331 run_test 1.3331 run_test pi