## arithmetic/src/basictypes/complex/ComplexTrans.mg

```GENERIC MODULE ComplexTrans(R, RT, C);
```
Arithmetic for Modula-3, see doc for details

Abstract: Transcendental functions of complex numbers.

```
IMPORT Arithmetic AS Arith;
IMPORT FloatMode;

<* UNUSED *>
CONST
Module = "ComplexTrans.";

PROCEDURE Arg (READONLY x: T; ): R.T =
BEGIN
RETURN RT.ArcTan2(x.im, x.re);
END Arg;

PROCEDURE PowR (READONLY x: T; y: R.T; ): T =
VAR
arg := Arg(x);
abs := Abs(x);
BEGIN
RETURN C.Scale(Exp(T{R.Zero, R.Mul(arg, y)}), RT.Pow(abs, y));
END PowR;

PROCEDURE Pow (x, y: T; ): T =
VAR z := Ln(x);
BEGIN
z := C.Mul(y, z);
z := Exp(z);
RETURN z;
END Pow;
```
This function would definitely benefit of an implementation of SinCos
```PROCEDURE Exp (READONLY x: T; ): T =
BEGIN
RETURN C.Scale(T{RT.Cos(x.im), RT.Sin(x.im)}, RT.Exp(x.re));
END Exp;
```
This function would definitely benefit of an implementation of SinCos
```PROCEDURE ExpI (x: R.T; ): T =
BEGIN
RETURN T{RT.Cos(x), RT.Sin(x)};
END ExpI;

PROCEDURE Ln (READONLY x: T; ): T =
VAR z: T;
BEGIN
(*z.re:= R.Div(RT.Ln(AbsSqr(x)),R.Two);*)
z.re := RT.Ln(AbsSqr(x)) / R.Two;
z.im := Arg(x);
RETURN z;
END Ln;

PROCEDURE Cos (READONLY x: T; ): T RAISES {Arith.Error} =
VAR z: T;
BEGIN
IF ABS(x.re) > FLOAT(18.0D0, R.T) OR ABS(x.im) > FLOAT(18.0D0, R.T) THEN
RAISE Arith.Error(NEW(Arith.ErrorOutOfRange).init());
END;
z.re := +RT.Cos(x.re) * RT.CosH(x.im);
z.im := -RT.Sin(x.re) * RT.SinH(x.im);
RETURN z;
END Cos;

PROCEDURE Sin (READONLY x: T; ): T RAISES {Arith.Error} =
VAR z: T;
BEGIN
IF ABS(x.re) > FLOAT(18.0D0, R.T) OR ABS(x.im) > FLOAT(18.0D0, R.T) THEN
RAISE Arith.Error(NEW(Arith.ErrorOutOfRange).init());
END;
z.re := +RT.Sin(x.re) * RT.CosH(x.im);
z.im := +RT.Cos(x.re) * RT.SinH(x.im);
RETURN z;
END Sin;

PROCEDURE Tan (READONLY x: T; ): T RAISES {Arith.Error} =
BEGIN
RETURN C.Div(Sin(x), Cos(x));
END Tan;

PROCEDURE CosH (READONLY x: T; ): T RAISES {Arith.Error} =
BEGIN
RETURN Cos(T{re := -x.im, im := +x.re});
END CosH;

PROCEDURE SinH (READONLY x: T; ): T RAISES {Arith.Error} =
VAR
(*z.re = -i*i*z.im = z.im*)
(*z.im = -i*z.re* = -z.re*)
z := Sin(T{-x.im, x.re});
BEGIN
RETURN T{z.im, -z.re};
END SinH;

PROCEDURE TanH (READONLY x: T; ): T RAISES {Arith.Error} =
BEGIN
RETURN C.Div(SinH(x), CosH(x));
END TanH;

PROCEDURE Norm1 (READONLY x: T; ): R.T =
BEGIN
RETURN ABS(x.re) + ABS(x.im);
END Norm1;

PROCEDURE NormInf (READONLY x: T; ): R.T =
BEGIN
RETURN MAX(ABS(x.re), ABS(x.im));
END NormInf;
```
Lemming's stuff

```PROCEDURE ArcSin (READONLY x: T; ): T =
VAR
ix := T{R.Neg(x.im), x.re};
BEGIN
(* arcsin x = -i ln (ix ± sqrt (1-x²)) *)
(*ix := C.Mul(x,C.I);*)
END ArcSin;

PROCEDURE ArcCos (READONLY x: T; ): T =
VAR y := SqRt(C.Sub(C.Square(x), C.One));
BEGIN
(* arccos x = -i ln (x ± sqrt (x²-1)) *)
END ArcCos;

PROCEDURE ArcTan (READONLY x: T; ): T RAISES {Arith.Error} =
VAR y := C.Div(C.Sub(C.I, x), C.Add(C.I, x));
BEGIN
(* arctan x := 1/2i ln ((i-x)/(i+x)) *)
RETURN C.Mul(Ln(y), T{R.Zero, RT.Half});
END ArcTan;

PROCEDURE Abs (READONLY x0: T; ): R.T =
VAR
x := C.Normalize(x0);
y := RT.SqRt(AbsSqr(x.val));
<* FATAL FloatMode.Trap *>
BEGIN
(* a workaround to prevent NaNs and Zeros *)
RETURN R.Scalb(y, x.exp);
END Abs;
```

PROCEDURE Abs (READONLY x:T;) : R.T = BEGIN RETURN RT.SqRt(AbsSqr(x)); END Abs;

```PROCEDURE AbsSqr (READONLY x: T; ): R.T =
BEGIN
(* RETURN C.Mul(x,C.Conj(x)); it's a real number, but the type is still
T *)
RETURN x.re * x.re + x.im * x.im;
END AbsSqr;

PROCEDURE SqRt (READONLY x: T; ): T =
VAR
r    := Abs(x);
z: T;
BEGIN
IF R.Compare(z.re, R.Zero) < 0 THEN (* mathematically impossible, can
be caused by rounding *)
z.re := R.Zero;
ELSE
z.re := RT.SqRt(R.Mul(z.re, RT.Half));
END;

z.im := R.Sub(r, x.re);
IF R.Compare(z.im, R.Zero) < 0 THEN (* mathematically impossible, can
be caused by rounding *)
z.im := R.Zero;
ELSE
z.im := RT.SqRt(R.Mul(z.im, RT.Half));
IF R.Compare(x.im, R.Zero) < 0 THEN (* instead of using the Sgn
function *)
z.im := R.Neg(z.im);
END;
END;
(* Root is on the same side as the radicand with respect to the real
axis. *)
RETURN z;
END SqRt;

BEGIN
END ComplexTrans.
```

interface FloatMode is in:

```

```