GENERIC MODULEPolarBasic (R, RT, C, CT);
Arithmetic for Modula-3, see doc for detailsAbstract: Complex numbers in polar coordinates
FROM Arithmetic IMPORT Error; <* UNUSED *> CONST Module = "PolarBasic."; PROCEDUREIsZero (READONLY x: T; ): BOOLEAN = BEGIN RETURN R.IsZero(x.radius); END IsZero; PROCEDUREEqual (READONLY x, y: T; ): BOOLEAN = BEGIN RETURN R.Equal(x.radius, y.radius) AND R.Equal(x.angle, y.angle); END Equal; PROCEDUREFromComplex (READONLY c: C.T; ): T = VAR x: T; BEGIN x.radius := CT.Abs(c); x.angle := RT.ArcTan2(c.im, c.re); RETURN x; END FromComplex; PROCEDUREToComplex (READONLY x: T; ): C.T = BEGIN RETURN C.Scale(C.T{re := RT.Cos(x.angle), im := RT.Sin(x.angle)}, x.radius); END ToComplex; PROCEDURENormalizeAngle (READONLY x: T; ): T = VAR angle := x.angle; BEGIN (*---normalize to -pi..+pi---*) (* if it was normalized before, the loops should run at most one cycle *) WHILE R.Compare(angle, RT.Pi) > 0 DO angle := R.Sub(angle, RT.TwoPi); END; WHILE R.Compare(angle, R.Neg(RT.Pi)) < 0 DO angle := R.Add(angle, RT.TwoPi); END; RETURN T{x.radius, angle}; END NormalizeAngle; PROCEDUREMul (READONLY x, y: T; ): T = VAR z: T; BEGIN z.radius := R.Mul(x.radius, y.radius); z.angle := R.Add(x.angle, y.angle); RETURN NormalizeAngle(z); END Mul; PROCEDUREDiv (READONLY x, y: T; ): T RAISES {Error} = VAR z: T; BEGIN z.radius := R.Div(x.radius, y.radius); z.angle := R.Sub(x.angle, y.angle); RETURN NormalizeAngle(z); END Div; BEGIN END PolarBasic.