78 lines
2.8 KiB
Text
78 lines
2.8 KiB
Text
/*NetRexx program to calculate the Nth root of X, with DIGS accuracy. */
|
|
class nth_root
|
|
|
|
method main(args=String[]) static
|
|
if args.length < 2 then
|
|
do
|
|
say "at least 2 arguments expected"
|
|
exit
|
|
end
|
|
x = args[0]
|
|
root = args[1]
|
|
if args.length > 2 then digs = args[2]
|
|
|
|
if root=='' then root=2
|
|
if digs = null, digs = '' then digs=20
|
|
numeric digits digs
|
|
say ' x = ' x
|
|
say ' root = ' root
|
|
say 'digits = ' digs
|
|
say 'answer = ' root(x,root,digs)
|
|
|
|
method root(x,r,digs) static --procedure; parse arg x,R 1 oldR /*assign 2nd arg-->r and rOrig. */
|
|
/*this subroutine will use the */
|
|
/*digits from the calling prog. */
|
|
/*The default digits is 9. */
|
|
R = r
|
|
oldR = r
|
|
if r=0 then do
|
|
say
|
|
say '*** error! ***'
|
|
say "a root of zero can't be specified."
|
|
say
|
|
return '[n/a]'
|
|
end
|
|
|
|
R=R.abs() /*use absolute value of root. */
|
|
|
|
if x<0 & (R//2==0) then do
|
|
say
|
|
say '*** error! ***'
|
|
say "an even root can't be calculated for a" -
|
|
'negative number,'
|
|
say 'the result would be complex.'
|
|
say
|
|
return '[n/a]'
|
|
end
|
|
|
|
if x=0 | r=1 then return x/1 /*handle couple of special cases.*/
|
|
Rm1=R-1 /*just a fast version of ROOT-1 */
|
|
oldDigs=digs /*get the current number of digs.*/
|
|
dm=oldDigs+5 /*we need a little guard room. */
|
|
ax=x.abs() /*the absolute value of X. */
|
|
g=(ax+1)/r**r /*take a good stab at 1st guess. */
|
|
-- numeric fuzz 3 /*fuzz digits for higher roots. */
|
|
d=5 /*start with only five digits. */
|
|
/*each calc doubles precision. */
|
|
|
|
loop forever
|
|
|
|
d=d+d
|
|
if d>dm then d = dm /*double the digits, but not>DM. */
|
|
numeric digits d /*tell REXX to use D digits. */
|
|
old=0 /*assume some kind of old guess. */
|
|
|
|
loop forever
|
|
_=(Rm1*g**R+ax)/R/g**rm1 /*this is the nitty-gritty stuff.*/
|
|
if _=g | _=old then leave /*computed close to this before? */
|
|
old=g /*now, keep calculation for OLD. */
|
|
g=_ /*set calculation to guesstimate.*/
|
|
end
|
|
|
|
if d==dm then leave /*found the root for DM digits ? */
|
|
end
|
|
|
|
_=g*x.sign() /*correct the sign (maybe). */
|
|
if oldR<0 then return _=1/_ /*root < 0 ? Reciprocal it is.*/
|
|
numeric digits oldDigs /*re-instate the original digits.*/
|
|
return _/1 /*normalize the number to digs. */
|