MODULE MathCplxSeries;
IMPORT NbrInt, NbrRe, NbrCplx, DataErrors;
TYPE
Coefficient* = OBJECT
VAR
n-: NbrInt.Integer;
z-: NbrCplx.Complex;
eos*: BOOLEAN;
coef*: NbrCplx.Complex;
PROCEDURE Evaluate*;
BEGIN
DataErrors.Error( "This function is abstract. It must be extended." )
END Evaluate;
END Coefficient;
VAR
epsilon: NbrRe.Real;
PROCEDURE ContinuedFraction*( a, b: Coefficient; z: NbrCplx.Complex ): NbrCplx.Complex;
VAR convergedLast, convergedThis: BOOLEAN; c, d, delta, f: NbrCplx.Complex;
BEGIN
a.n := 0; a.z := z; a.eos := FALSE; b.n := 0; b.z := z; b.eos := FALSE; b.Evaluate;
IF b.coef = 0 THEN b.coef := 1/NbrRe.MaxNbr END;
f := b.coef; c := f; d := 0;
convergedThis := FALSE;
REPEAT
NbrInt.Inc( a.n ); a.Evaluate; NbrInt.Inc( b.n ); b.Evaluate; c := b.coef + a.coef * z / c;
d := 1 / (b.coef + a.coef * z * d); delta := c * d; f := delta * f; convergedLast := convergedThis;
convergedThis := NbrRe.Abs( 1 - NbrCplx.Abs( delta ) ) < epsilon
UNTIL (convergedLast & convergedThis) OR (a.eos OR b.eos);
RETURN f
END ContinuedFraction;
PROCEDURE TruncatedContinuedFraction*( a, b: ARRAY OF NbrRe.Real; z: NbrCplx.Complex ): NbrCplx.Complex;
VAR i, aLen, bLen: NbrInt.Integer; c, d, f: NbrCplx.Complex;
BEGIN
aLen := LEN( a ); bLen := LEN( b );
IF aLen # bLen THEN
DataErrors.Error( "Lengths of supplied arrays must be equal." ); f := 0; RETURN f END;
IF b[0] = 0 THEN b[0] := 1/NbrRe.MaxNbr END;
f := b[0]; c := f; d := 0; i := 1;
REPEAT c := b[i] + a[i] * z / c; d := 1 / (b[i] + a[i] * z * d); f := c * d * f; NbrInt.Inc( i ) UNTIL i = aLen;
RETURN f
END TruncatedContinuedFraction;
PROCEDURE PowerSeries*( a: Coefficient; z: NbrCplx.Complex ): NbrCplx.Complex;
VAR convergedLast, convergedThis: BOOLEAN; sum, update, zz: NbrCplx.Complex;
BEGIN
a.z := z; a.n := 0; a.eos := FALSE; a.Evaluate; sum := a.coef; zz := 1; convergedThis := FALSE;
REPEAT
NbrInt.Inc( a.n ); a.Evaluate; zz := z * zz; update := a.coef * zz; sum := sum + update;
convergedLast := convergedThis; convergedThis := NbrCplx.Abs( update ) < (epsilon * NbrCplx.Abs( sum ))
UNTIL (convergedLast & convergedThis) OR a.eos;
RETURN sum
END PowerSeries;
PROCEDURE TruncatedPowerSeries*( a: ARRAY OF NbrRe.Real; z: NbrCplx.Complex ): NbrCplx.Complex;
VAR i, len: NbrInt.Integer; prod: NbrCplx.Complex;
BEGIN
len := LEN( a ); prod := a[len - 1] * z;
FOR i := len - 2 TO 1 BY -1 DO prod := (a[i] + prod) * z END;
prod := a[0] + prod; RETURN prod
END TruncatedPowerSeries;
PROCEDURE RationalFunction*( a, b: Coefficient; z: NbrCplx.Complex ): NbrCplx.Complex;
VAR denom, num, ratio: NbrCplx.Complex;
BEGIN
num := PowerSeries( a, z ); denom := PowerSeries( b, z ); ratio := num / denom; RETURN ratio
END RationalFunction;
PROCEDURE TruncatedRationalFunction*( a, b: ARRAY OF NbrRe.Real; z: NbrCplx.Complex ): NbrCplx.Complex;
VAR denom, num, ratio: NbrCplx.Complex;
BEGIN
num := TruncatedPowerSeries( a, z ); denom := TruncatedPowerSeries( b, z ); ratio := num / denom;
RETURN ratio
END TruncatedRationalFunction;
BEGIN
epsilon := 10 * NbrRe.Epsilon
END MathCplxSeries.