home *** CD-ROM | disk | FTP | other *** search
- { POWERN.PLB #1.04 85-06-22 FAST INTEGER POWERS OF REAL NUMBERS
-
- V01 L04 pretty-print update on 85-06-22 with expanded remarks by DEH
- L03 update on 85-06-18 by DEH to expand on an unpublished idea
- of David Gries.
- L02 update on 85-06-11 by DEH for draft DDJ pretty printing.
- L01 update on 85-06-09 by DEH to smooth out some rough edges.
- L00 created on 85-06-05 by Dennis E. Hamilton in order to answer
- a number of electronic requests for help with Pascal powers.}
-
- function
-
- PowerN(x: real; {initial value: x0}
- n: integer {required exponent} )
-
- :real {value of x0^n or x0**n};
-
- var i: integer {non-negative power of x which remains to be computed};
- r: real {running intermediate-result value};
-
- procedure
-
- MakeOdd;
-
- begin {V01 L03 Knuth transformation re-ordered to exploit
- initial i > 0 and even, thanks to the Gries adjustment.}
- repeat {reduction of i while preserving x0^abs(n) = r*x^i}
- x := sqr(x);
- i := i shr 1;
- {or use i := i div 2 when shifting is not supported}
- until odd(i);
- end; {transformation of x^(2*k) to sqr(x)^k until odd k reached}
-
- BEGIN {PowerN}
-
- if n = 0
- then begin
- if abs(x) = 0.0
- {V01 L01: Insulating against Turbo Pascal and
- IEEE -0.0 possibilities}
- then PowerN := x/x
- {In the indeterminate 0^0 case, defer to the system's
- treatment of 0/0 for appropriate continuation.}
- else PowerN := 1.0;
- end
- else begin {n <> 0 now guaranteed}
- i := abs(n);
- if not odd(i) then MakeOdd;
- {V01 L03 odd(i) now guaranteed}
- r := x; i := pred(i);
- {V01 L03 even(i) now guaranteed for the Gries invariant}
- while i <> 0
- do begin {not odd(i) and x0^abs(n) = r*x^i}
- MakeOdd;
- r := r*x; i := pred(i);
- end {Gries-invariant version of the Knuth transformation
- as re-expressed in Dijkstra-Jensen-Wirth form};
- if n < 0
- then PowerN := 1.0/r
- else PowerN := r;
- end;
-
- END {PowerN};