Chris Angelico wrote:
Wow, someone else who knows REXX and OS/2! REXX was the first bignum
language I met, and it was really cool after working in BASIC and
80x86 assembly to suddenly be able to work with arbitrary-precision
numbers!
Yes, my "big num" research stuff was initially done in REXX, on VM/CMS.
I later ported my libraries over to OS/2 and continued with that well
into the '90s, when I discovered Unix and 'bc'. Many folks are not
aware that 'bc' also has arbitrary precision floating point math and a
standard math library. It is much faster than REXX because the libraries
are written in C, and unlike REXX they do not have to be implemented in
the interpreter. The syntax of 'bc' is C-like, which is its only
down-side for new students who have never had any language training.
REXX was a great business language, particularly when CMS Pipelines was
introduced.
Just for fun, and a trip down memory lane, you can take a look at some
of my ancient REXX code... this code is a REXX math library designed to
be used from the command line, written in REXX. The primary scientific
functions were implemented, as well as some code to calculate PI...
most of the algorithms can be ported to 'bc' easily, but the 'bc'
algorithms will run much faster, of course.
Back in the day, REXX was the 'new BASIC'
... now I use Python.
/********************************************************************/
/********************************************************************/
/** COMPUTE COMMAND LINE SCIENTIFIC CALCULATOR **/
/********************************************************************/
/********************************************************************/
/** **/
/** IBM Corporation **/
/** HARRISMH at RCHVMP2 **/
/** EL8/663-1 B627 **/
/** Rochester, MN 55901 **/
/** **/
/** AUTHOR: Marcus Harris **/
/** DATE: 93/10/22 ( port from VM/CMS ) **/
/** UPDATE: 98/03/07 **/
/** VER: 2.0a **/
/** **/
/********************************************************************/
/********************************************************************/
/** syntax **/
/** **/
/** COMPUTE expression<;expression><;expression><@digits> **/
/** **/
/** **/
/** The expression(s) will be computed and displayed in terminal **/
/** line mode to arbitrary <@digits> of accuracy. **/
/** **/
/** The expression(s) may be any REXX math clause and may include **/
/** a variable assignment, for use in a subsequent expression: **/
/** ie., COMPUTE A=3;B=7;A/B;A*B@30 **/
/** (will compute both the quotient and product of A & B) **/
/** **/
/********************************************************************/
/********************************************************************/
/** NOTES **/
/** **/
/** COMPUTE expression<;expression><;expression><@digits> **/
/** **/
/** This program exploits Rexx INTERPRET and NUMERIC DIGITS **/
/** **/
/** This exec is portable to OS/2, NT and w95 Rexx/objectRexx **/
/** without changes. **/
/** **/
/********************************************************************/
/********************************************************************/
/** updates **/
/** 93/10/21 mhh New Program (port from VM/CMS) **/
/** 98/03/07 mhh New Version 2.0a **/
/** This version includes trigonometric, logarithmic, **/
/** exponential and combinatorial functions. **/
/** **/
/** See the REXROOTS ABOUT file for a discussion **/
/** of the included functions and some examples, **/
/** using the COMPUTE program. **/
/** **/
/********************************************************************/
/********************************************************************/
/** dependencies **/
/** **/
/** Numeric Fuzz: **/
/** Most of these routines bump-up the numeric digits **/
/** by a fuzzFactor. Rexx fuzz is used to terminate **/
/** the do-forever iteration at the correct number of **/
/** required places. **/
/** The routine then sets the numeric digits back to **/
/** the application setting and returns result-0. **/
/** The (result-0) forces truncation/rounding to give **/
/** the expected result. **/
/** Some implementations of REXX do not support the **/
/** fuzz option; the iterative do-forever methods **/
/** would need modification for correct termination. **/
/** **/
/********************************************************************/
/********************************************************************/
/** mainline **/
/********************************************************************/
arg expression '@' max_digits .
select
when expression='' | expression='?' then say syntax_diagram()
when datatype(max_digits,'W') & max_digits>0 then,
numeric digits max_digits
otherwise
numeric digits 18
end
call evaluate expression
exit 0
/********************************************************************/
/** procedures **/
/********************************************************************/
SYNTAX_DIAGRAM: procedure
return'Syntax: COMPUTE expression <;expression><@precision>'
EVALUATE: procedure expose max_digits
arg expression
signal on error; signal on syntax
/* 502 digits pi/2 */
hpi="1.57079632679489661923132169163975144209858469968755291048747229615390820314310449931401741267105853"
hpi=hpi"3991074043256641153323546922304775291115862679704064240558725142051350969260552779822311474477465190"
hpi=hpi"9822144054878329667230642378241168933915826356009545728242834617301743052271633241066968036301245706"
hpi=hpi"3686229350330315779408744076046048141462704585768218394629518000566526527441023326069207347597075580"
hpi=hpi"471652863518287979597654609305869096630589655255927403723118998137478367594287636244561396909150597456"
/* 502 digits pi */
pi="3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679"
pi=pi"8214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196"
pi=pi"4428810975665933446128475648233786783165271201909145648566923460348610454326648213393607260249141273"
pi=pi"7245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094"
pi=pi"3305727036575959195309218611738193261179310511854807446237996274956735188575272489122793818301194912"
resetTime=time('R')
do while expression <> ''
parse value expression with exp1';'expression
select
when pos('=',exp1)<>0 then do
interpret 'do; 'exp1'; end;'
end
otherwise
interpret 'do; answer='exp1'; end;'
select
when answer='' then say syntax_diagram()
when datatype(answer,'N') then say answer
otherwise signal error
end
end
end
say "elapsed time:" time('E')
return
/********************************************************************/
/** routines **/
/********************************************************************/
ERROR:; SYNTAX:
say 'Does Not Compute'
exit 28
/********************************************************************/
/** functions **/
/********************************************************************/
fx: procedure /* template
*/
arg x
maxDigits=digits()
numeric digits maxDigits*2
numeric fuzz maxDigits
/* f(x) goes here */
numeric fuzz 0
numeric digits maxDigits
return x-0
/********************************************************************/
/** Exponential - Logarithmic **/
/********************************************************************/
exp: procedure /* (a>=0) (n>=0)
*/
arg a,n
select
when datatype(n, "W")=1 then x=a**n
otherwise x=e(ln(a)*n)
end
return x
ln: procedure /* series methods ( x > 0 ) */
arg x
if x<=0 then return "ERROR"
maxDigits=digits()
numeric digits maxDigits+7
numeric fuzz 7
select
when x>80 then do
i=0
do while x>=5
i=i+1
x=x/10
end
x=ln(x)+i*ln(10)
end
when x<.5 then do
i=0
do while x<.5
i=i+1
x=x*10
end
x=ln(x)-i*ln(10)
end
when x>1.6 then do
u=(x-1)/(x+1); x=u; c=1; s=u**2
do forever
c=c+1
u=s*u
x1=x+u/(2*c-1)
if x1=x then leave
x=x1
end
x=x*2
end
otherwise
u=(x-1); x=u; c=1; s=u; sign=1
do forever
c=c+1
u=u*s
sign=sign*(-1)
x1=x+sign*u/c
if x1=x then leave
x=x1
end
end
numeric fuzz 0
numeric digits maxDigits
return x-0
e: procedure /* (all real x)
e^x = 1+x+x^2/2!+x^3/3!-x^4/4!... */
arg x
maxDigits=digits()
select
when x<(-5) then do
fuzzFactor=abs(x)%5
numeric digits maxDigits*fuzzFactor
numeric fuzz maxDigits*(fuzzFactor-1)
end
otherwise
numeric digits maxDigits+7
numeric fuzz 7
end
n=x; s=x; x=x+1; d=1; c=1
do forever
c=c+1
n=n*s
d=d*c
x1=x+n/d
if x1=x then leave
x=x1
end
numeric fuzz 0
numeric digits maxDigits
return x-0
/********************************************************************/
/** Trigonometric **/
/********************************************************************/
tan: procedure /* (all real x)
*/
arg x,hyper
maxDigits=digits()
numeric digits maxDigits*2
numeric fuzz maxDigits
if hyper="" then x=sin(x)/cos(x)
else x=sinh(x)/cosh(x)
numeric fuzz 0
numeric digits maxDigits
return x-0
tanh: procedure /* (all real x)
*/
arg x
return tan(x,"h")
cos: procedure /* (all real x)
cos(x)=1-x^2/2!+x^4/4!-x^6/6!...
cosh(x)=1+x^2/2!+x^4/4!+x^6/6!... */
arg x,hyper
maxDigits=digits()
numeric digits maxDigits*2
numeric fuzz maxDigits
n=1; s=x**2; x=1; sign=1; d=1; c=1
select
when hyper="" then do forever /* cosine function */
c=c+1
n=n*s
sign=(-1)*sign
do i=2 to 3 by 1
d=d*(2*c-i)
end
x1=x+sign*n/d
if x1=x then leave
x=x1
end
otherwise
do forever /* hyperbolic cosine function */
c=c+1
n=n*s
do i=2 to 3 by 1
d=d*(2*c-i)
end
x1=x+n/d
if x1=x then leave
x=x1
end
end
numeric fuzz 0
numeric digits maxDigits
return x-0
cosh: procedure /* (all real x)
*/
arg x
return cos(x,"h")
sin: procedure /* (all real x)
sin(x)=x/1!-x^3/3!+x^5/5!-x^7/7!...
sinh(x)=x/1!+x^3/3!+x^5/5!+x^7/7!... */
arg x,hyper
maxDigits=digits()
numeric digits maxDigits*2
numeric fuzz maxDigits
n=x; s=x**2; sign=1; d=1; c=1
select
when hyper="" then do forever /* sine function */
c=c+1
n=n*s
sign=(-1)*sign
do i=1 to 2 by 1
d=d*(2*c-i)
end
x1=x+sign*n/d
if X1=x then leave
x=x1
end
otherwise
do forever /* hyperbolic sine Function */
c=c+1
n=n*s
do i=1 to 2 by 1
d=d*(2*c-i)
end
x1=x+n/d
if X1=x then leave
x=x1
end
end /*select*/
numeric fuzz 0
numeric digits maxDigits
return x-0
sinh: procedure /* (all real x)
*/
arg x
return sin(x,"h")
sin_1: procedure expose hpi /* ( x^2<1 -pi/2 < sin_1(x) < pi/2 )
sin_1(x)=x+(x^3/2*3)+(x^5*1*3/2*4*5)+(x^7*1*3*5/2*4*6*7)... */
arg x
if x**2 >1 then return "ERROR"
maxDigits=digits()
numeric digits maxDigits*2
numeric fuzz maxDigits
n=x; d=1; s=x**2; c=1; p=0
if abs(x)>(.7854) then do
p=1; if x<0 then p=-1
s=1-s; x=sqrt(s); n=x
end
do forever
c=c+1; cc=2*c
n=n*(cc-3)*s
d=d*(cc-2)
x1=x+n/(d*(cc-1))
if x1=x then leave
x=x1
end
numeric fuzz 0
numeric digits maxDigits
select
when p>0 then return hpi-x
when p<0 then return x-hpi
otherwise nop
end
return x-0
cos_1: procedure expose hpi /* ( x^2<1 0 < cos_1(x) < pi )
*/
arg x
return hpi-sin_1(x)
tan_1: procedure expose hpi /* ( all real x )
*/
arg x
return hpi-cos_1(x/sqrt(x**2+1))
/********************************************************************/
/** Combinatorial **/
/********************************************************************/
fact: procedure /* n! n=(0,1,2,3...) */
arg n
numeric digits 500
m=1
do i=2 to n by 1
m=i*m
end
return m
part: procedure /* Ordered Partition */
arg m parts
numeric digits 500
mFact=fact(m)
do while parts<>''
parse var parts part parts
if datatype(part,'W') & m-part>=0 then do
m=m-part
mFact=mFact/fact(part)
end
end
return mFact/fact(m)
/********************************************************************/
/** PI routines **/
/********************************************************************/
PI: procedure /* AGM Gauss-Legendre Method
Crandall: Projects In Scientific Computation */
arg n
maxDigits=digits()
numeric digits maxDigits+7
numeric fuzz 7
x=sqrt(2); p=2+x; y=sqrt(x)
do forever
s=sqrt(x)
x=(s+1/s)/2
p1=p*((x+1)/(y+1))
if p1=p then leave
p=p1
s=sqrt(x)
y=((y*s)+(1/s))/(y+1)
end
numeric fuzz 0
numeric digits maxDigits
return p-0
PIa: procedure /* AGM Gauss-Legendre Method */
arg n
maxDigits=digits()
numeric digits maxDigits+7
numeric fuzz 7
a=1; b=1/sqrt(2); t=1/4; x=1
do i=1 to 100
y=a
a=(a+b)/2
b=sqrt(b*y)
if a=b then leave
t=t-x*(y-a)**2
x=2*x
end
PI=((a+b)**2)/(4*t)
numeric fuzz 0
numeric digits maxDigits
return PI-0
/********************************************************************/
/** Roots **/
/********************************************************************/
sqrt: procedure /* (all real x) */
arg x
return nrt(x,2)
cbrt: procedure /* (all real x) */
arg x
return nrt(x,3)
nrt: procedure /* ( a>=0 ) ( n>=0 )
*/
arg a,n
maxDigits=digits()
numeric digits maxDigits+7
numeric fuzz 7
if a=1 | a=0 then return a
if n=0 then return 1
if a<0 | n<0 then return "ERROR"
select
when datatype(n, "W" )=1 then do
m=n-1
x=bisect(a,n)
do forever /* Newton Method x:= x - ( f(x)/f'(x) ) */
x1=(m*x**n+a)/(n*x**m)
if x1=x then leave
x=x1
end
end
otherwise
x=e(ln(a)/n)
end
numeric fuzz 0
numeric digits maxDigits
return x-0
bisect: procedure /* Bisect Method used to seed nrt() */
arg n,root /* (n>=0) (root: 2,3,4,5,6...) */
numeric digits 12
numeric fuzz 3
a=0; b=n
if n<1 then b=1
else a=1
do forever
m=(a+b)/2
Fm=m**root-n
select
when Fm>0 then b=m
when Fm<0 then a=m
otherwise
a=b
end
if a=b then leave
end
return b
--
http://mail.python.org/mailman/listinfo/python-list