MODULE MathCbrt;
IMPORT NbrInt, NbrRe, NbrCplx, DataErrors, MathReSeries;
VAR
cbrt2: NbrRe.Real;
cbrtP, cbrtQ: ARRAY 3 OF NbrRe.Real;
PROCEDURE Fn*( x: NbrRe.Real ): NbrRe.Real;
VAR isNeg: BOOLEAN;
i, exponent, mod: NbrInt.Integer; cbrtRadix, cubeRoot, mantissa, ratFn, update: NbrRe.Real;
BEGIN
IF NbrRe.Radix = 2 THEN cbrtRadix := cbrt2
ELSIF NbrRe.Radix = 4 THEN cbrtRadix := cbrt2 * cbrt2
ELSIF NbrRe.Radix = 8 THEN cbrtRadix := 2
ELSIF NbrRe.Radix = 16 THEN cbrtRadix := 2 * cbrt2
ELSIF NbrRe.Radix = 32 THEN cbrtRadix := 2 * cbrt2 * cbrt2
ELSE DataErrors.Error( "Not implemented for this CPU." ); RETURN 0
END;
mantissa := NbrRe.Mantissa( x ); exponent := NbrRe.Exponent( x );
IF mantissa > 0 THEN isNeg := FALSE ELSE isNeg := TRUE; mantissa := NbrRe.Abs( mantissa ) END;
mantissa := mantissa / NbrRe.Radix;
ratFn := MathReSeries.TruncatedRationalFunction( cbrtP, cbrtQ, mantissa );
IF isNeg THEN mantissa := -ratFn ELSE mantissa := ratFn END;
mod := exponent MOD 3;
IF mod = 0 THEN cubeRoot := NbrRe.Re( cbrtRadix * mantissa, exponent DIV 3 )
ELSIF mod = 1 THEN cubeRoot := NbrRe.Re( cbrtRadix * cbrtRadix * mantissa, (exponent + 1) DIV 3 )
ELSE cubeRoot := NbrRe.Re( NbrRe.Radix * mantissa, (exponent - 1) DIV 3 )
END;
FOR i := 1 TO 3 DO
update := cubeRoot - (cubeRoot - x / (cubeRoot * cubeRoot)) / 3; cubeRoot := update
END;
RETURN cubeRoot
END Fn;
PROCEDURE CplxFn*( z: NbrCplx.Complex ): NbrCplx.Complex;
VAR abs, arg, im, re: NbrRe.Real; cbrt: NbrCplx.Complex;
BEGIN
im := NbrCplx.Im( z );
IF im = 0 THEN
re := NbrCplx.Re( z );
IF re # 0 THEN NbrCplx.Set( Fn( re ), 0, cbrt ) ELSE cbrt := 0 END
ELSE abs := NbrCplx.Abs( z ); arg := NbrCplx.Arg( z ); NbrCplx.SetPolar( Fn( abs ), arg / 3, cbrt )
END;
RETURN cbrt
END CplxFn;
BEGIN
cbrt2 := 1.25992105;
cbrtP[0] := 0.17782942E-1; cbrtP[1] := 0.885812034; cbrtP[2] := 1.76794059;
cbrtQ[0] := 0.99419338E-1; cbrtQ[1] := 1.57522016; cbrtQ[2] := 1.0
END MathCbrt.