RxxMath

Автор: John Brock

Дата: 1996

Скачать архив.

      RXXMATH v1.3 -- Arbitrary Precision Math Functions for REXX

                   Copyright 1992, 1996 by John Brock

RXXMATH is an extremely easy-to-use math package which may be called as

an external routine from REXX or invoked from the command line.  RXXMATH

is true to the spirit of REXX math in that it will calculate results to

arbitrary precision.  Because RXXMATH is itself written entirely in REXX

it should port essentially unchanged to any environment which supports

REXX.  (RXXMATH was originally written for VM/CMS, but the author has

also run it under MVS/TSO, IBM PC DOS 7, and OS/2).  Note that along

with the basic math functions RXXMATH has an interpretative calculator

function which may be used to evaluate complex mathematical expressions,

or even used as a interactive "REXX shell".

 

This RXXMATH distribution is for OS/2, and includes the files:

RXXMATH.CMD  -- the main program

RXXMATHI.CMD -- support for the interpretative REXX calculator function

RXXMATH.DOC  -- this documentation file

 

RXXMATH is unsupported freeware, and is provided "as is", with no

warranties of any sort, express or implied.  RXXMATH may be freely

distributed in any format, provided no alterations are made to the files

(other than what may be necessary to port RXXMATH to a new environment)

and no restrictions are placed on further distribution.  Users may

modify RXXMATH at their convenience, as long as the copyright notices

are retained and the modified version is not distributed publicly.

Comments are welcome, and may be sent to jbrock@panix.com.

 

The following functions are supported:

            FACT(x)    --  Factorial of x

            PERM(x,y)  --  Permutations of x by y

            COMB(x,y)  --  Combinations of x by y

            SQRT(x)    --  Square root of x

            POW(x,y)   --  x to the power of y

            LOG(x,y)   --  Log of y base x

            EXP(x)     --  e to the power of x

            LN(x)      --  Natural log of x

            PI()       --  Value of pi

            SIN(x)     --  Sine of x

            COS(x)     --  Cosine of x

            TAN(x)     --  Tangent of x

            COT(x)     --  Cotangent of x

            SEC(x)     --  Secant of x

            CSC(x)     --  Cosecant of x

            ARCSIN(x)  --  Inverse sine of x

            ARCCOS(x)  --  Inverse cosine of x

            ARCTAN(x)  --  Inverse tangent of x

            ARCCOT(x)  --  Inverse cotangent of x

            ARCSEC(x)  --  Inverse secant of x

            ARCCSC(x)  --  Inverse cosecant of x

            CALC(x)    --  Calculate the value of an expression

                             (e.g. '1 + exp(pi() / 2)')

 

When invoked from the command line, RXXMATH has the format:

+----------------------------------------------------------------------+

| RXXMATH [digits] function [x [y]]                                    |

+----------------------------------------------------------------------+

When called as a function from REXX, RXXMATH has the format:

+----------------------------------------------------------------------+

| RXXMATH([digits,] function [,x [,y]])                                |

+----------------------------------------------------------------------+

Where:      digits     is the desired precision of the result

                         (if omitted or zero the NUMERIC DIGITS

                          default, which should be 9, is used)

            function   is the name of a supported function

            x, y       are arguments to the function

 

Examples:

1. From the command line, find the square root of 2 to 40 places:

       rxxmath 40 sqrt 2  (or rxxmath 40 pow 2 0.5)

   result: 1.41421356237309504880168872420969807857

 

2. Find the square root of 2 to 9 places (the default):

       rxxmath sqrt 2

   result: 1.41421356

 

3. From within REXX, print the base 10 log of 5 to 40 places:

       say rxxmath(40, "LOG", 10, 5)

   result: 0.6989700043360188047862611052755069732318

 

4. From REXX, print the base 10 log of 5 to 9 places:

       say rxxmath("LOG", 10, 5)

   result: 0.698970004

 

5. From REXX, print 1 plus e to the power of pi/2, to 50 places:

       say rxxmath(50, "CALC", "1 + exp(pi() / 2)")

   result: 5.8104773809653516554730356667038331263901708746645

 

6. From the command line, find "1 + exp(pi() / 2)" to 9 places:

       rxxmath calc 1 + exp(pi() / 2)

   result: 5.81047738

 

7. Enter interactive REXX calculator mode (a "REXX shell"):

       rxxmath calc

   result: RXXMATH interactive mode -- enter any valid REXX instruction:

           a = 1 + exp(pi() / 2)

           RXXMATH interactive mode -- enter any valid REXX instruction:

           say a

           5.8104774

           RXXMATH interactive mode -- enter any valid REXX instruction:

           numeric digits 50

           RXXMATH interactive mode -- enter any valid REXX instruction:

           b = 1 + exp(pi() / 2); say b

           5.8104773809653516554730356667038331263901708746648

           RXXMATH interactive mode -- enter any valid REXX instruction:

           prompt = "New prompt:"

           New prompt:

           numeric digits 9

           New prompt:

           say pi() - ln(23)

           0.00609843

           New prompt:

           say calc("pi() - ln(23)")

           0.00609843766

           New prompt:

           say calc(pi() - ln(23))

           0.00609843

           New prompt:

           exit

 

Notes:

If invoked without arguments from the command line, RXXMATH will print a

help message.

 

When invoked as a command RXXMATH normally prints its result to the

screen and returns 0. If there is an error it prints an error message

and returns 1. When called as a REXX function RXXMATH normally returns

its result to REXX and prints nothing.  If there is an error RXXMATH

prints an error message and returns no value to REXX.  This will cause

the SYNTAX condition to be raised, which is consistent with the behavior

of REXX built-in functions when given bad arguments.  However if

necessary you can avoid raising the SYNTAX condition on error by calling

RXXMATH as a subroutine, rather than a function.

 

All trigonometric function arguments are in radians.

 

In general the numeric arguments to an RXXMATH function may be any legal

REXX numbers, of any size and precision.  If an argument has more

significant digits than the requested precision of the result the

argument will be rounded before use.  Of course an attempt to use a

number outside the range of a given function (e.g., SQRT(-2) or

FACT(3.3)) will result in an error.  Arguments to the trigonometric

functions may not be of arbitrary size, but must have an absolute value

which is < 10 ** (precision % 2).  So, for example, using a precision of

9 you could calculate sin(9999), but trying to calculate sin(10000)

would result in an error.  In the unlikely event that you really need to

calculate the sine or cosine of a very large number it can be done by

increasing the size of the of the precision argument until the above

condition is met (which may however result in an unacceptably long

execution time).

 

RXXMATH uses REXX's arbitrary precision arithmetic to calculate its

results, so naturally if an implementation of REXX does not support this

feature of the language then RXXMATH's ability to return high precision

results will be limited.  RXXMATH sets its internal precision twice as

high as requested by the user, so if, for example, the highest precision

a given implementation of REXX will support is 100, then the highest

precision the user may request from RXXMATH is 50.

 

Some performance considerations.  When the precision is <= 25 RXXMATH

can use hard coded values for e and pi (which are used internally a

lot), and ln(10) (which provides a special boost for log base 10

calculations).  The POW function knows when it is being asked to take a

square root (e.g., RXXMATH("POW", 0.25, -1.5) = 8), and uses the

considerably faster SQRT function when appropriate.  And RXXMATH can

recognize situations that REXX can deal with directly, such as integer

powers, so that, for example, RXXMATH("POW", 2.5, 10) will execute much

faster than RXXMATH("POW", 2.5, 10.1).

 

All calculations are done in the main program, RXXMATH, which may be

compiled if a REXX compiler is available.  RXXMATHI (which is called

only by RXXMATH, never by the user) supports the interpretative REXX

calculator function ("CALC"), and because it uses the "interpret"

statement it may not be compiled.  Note that RXXMATH and RXXMATHI call

each other when the CALC function is used, so this function will not

work unless they are placed in locations where they can find each other

automatically.

 

The CALC function takes a character string and interprets it as a REXX

expression, using the RXXMATH math functions with names and arguments as

listed above (e.g., "exp(4)" is replaced by the appropriate call to

RXXMATH itself).  In addition to the math functions supplied by RXXMATH,

the expression may contain any REXX built-in functions or any external

functions which return a numeric result.

 

If you call the CALC function without any arguments you will go into the

interactive REXX calculator mode ("REXX shell").  From there you can

issue any valid REXX instructions, using any of the math functions

supported by RXXMATH, as well as any other functions or commands usable

from within REXX.  When you enter interactive mode you will be prompted

for input.  The prompt string is contained in the REXX variable

"prompt", and may be altered or suppressed by changing or dropping that

variable.  In addition, if there are lines in the external data queue

the prompt is suppressed while those lines are read and executed.  The

"return" or "exit" instructions will take you out of interactive mode,

and may be used to return a value if desired.

 

The basic RXXMATH math functions are all highly accurate, and the CALC

function inherits their accuracy, but because the CALC function

evaluates arbitrary mathematical expressions in a straightforward

numerical way (rather than symbolically) the need for error analysis is

not eliminated.  Consider the following methods for calculating the

expression "pi() - ln(23)", using the default precision of 9.

 

1.  a = rxxmath("PI") - rxxmath("LN", 23) /* CALC is avoided. */

2.  queue 'a = pi() - ln(23)'

    queue 'return a'

    b = rxxmath("CALC") /* Interactive CALC (queued instructions). */

3.  c = rxxmath("CALC", "pi() - ln(23)") /* Non-interactive CALC. */

 

Methods 1 and 2 are exactly equivalent, and set a = b = 0.00609843.

Method 3 gives more precision, setting c = 0.00609843766.  In the first

two cases pi() and ln(23) are both calculated (accurately) to 9 places,

and their difference is taken, giving a result with fewer than 9 digits

of precision.  In case 3 RXXMATH calculates both pi() and ln(23) to 18

places, takes the difference, and then rounds the final result to 9

significant digits before returning it, which gives a better result.

 

Note that CALC is itself a perfectly legitimate RXXMATH function, and

therefore can be evaluated by CALC.  For example, you can call CALC

non-interactively while in RXXMATH interactive mode, as was done in

Example 7 above.  Just make sure the argument is a quoted string, or

your expression will be evaluated too early and the benefit lost.

 

History:

v1.3 (19 Nov 1996)

The name of the package was changed from RXMATH to RXXMATH to avoid a

name conflict with an unrelated package of math functions for REXX.

The negation operator was changed from "^" (caret) to "\" (backslash).

The code that prints a help message when RXXMATH is invoked without

arguments was changed so that it no longer reads the message from the

leading comment using SOURCELINE().  This means the the message will

still print even if RXXMATH is compiled and the comments stripped out.

Some built-in REXX functions -- DIGITS(), WORDPOS(), and LINES() -- were

not available when the code was first written, and so were coded

explicitly into the program.  These have been stripped out, on the

assumption that these functions should be included as built-ins in all

current REXX implementations.

The documentation was partially rewritten.

Other minor changes, mostly for readability.

 

v1.2 (15 Oct 1992)

Various changes to make the code SAA compliant.

 

v1.1 (7 Sep 1990)

Minor changes for running under MVS/TSO.

 

v1.0 (8 Sep 1989)

Original version for VM/CMS.