Unit MathFunc;

Interface

Uses pr_defs, math, progdefs, pr_bdef;

{All the internal functions used by the external code:}
Procedure pf_sqrt;
Procedure pf_power;
Procedure pf_sin;
Procedure pf_cos;
Procedure pf_tan;
Procedure pf_csc;
Procedure pf_sec;
Procedure pf_cot;
Procedure pf_arcsin;
Procedure pf_arccos;
Procedure pf_arctan;
Procedure pf_normalize;
Procedure pf_vlen;

Implementation

Procedure pf_sqrt;
Begin
  pr_globals^[OFS_RETURN] := sqrt(G_FLOAT(OFS_PARM0));
End;

{Raising number to an exponent:}
Procedure pf_power;
Begin
  pr_globals^[OFS_RETURN] := Exp(Ln(G_FLOAT(OFS_PARM0))*G_FLOAT(OFS_PARM1));
End;

{Basic TRIG:}
Procedure pf_sin;
Begin
  pr_globals^[OFS_RETURN] := sin(G_FLOAT(OFS_PARM0));
End;

Procedure pf_cos;
Begin
  pr_globals^[OFS_RETURN] := cos(G_FLOAT(OFS_PARM0));
End;

Procedure pf_tan;
Begin
  If cos(G_FLOAT(OFS_PARM0)) = 0 Then PR_RunError('Error: TAN domain.');
  pr_globals^[OFS_RETURN] := sin(G_FLOAT(OFS_PARM0)) / cos(G_FLOAT(OFS_PARM0));
End;

Procedure pf_csc;
Begin
  If sin(G_FLOAT(OFS_PARM0)) = 0 Then PR_RunError('Error: CSC domain.');
  pr_globals^[OFS_RETURN] := 1.0/sin(G_FLOAT(OFS_PARM0));
End;

Procedure pf_sec;
Begin
  If cos(G_FLOAT(OFS_PARM0)) = 0 Then PR_RunError('Error: SEC domain.');
  pr_globals^[OFS_RETURN] := 1.0/cos(G_FLOAT(OFS_PARM0));
End;

Procedure pf_cot;
Begin
  If sin(G_FLOAT(OFS_PARM0)) = 0 Then PR_RunError('Error: COT domain.');
  pr_globals^[OFS_RETURN] := cos(G_FLOAT(OFS_PARM0)) / sin(G_FLOAT(OFS_PARM0));
End;

{Don't try to understand it. It works.}
Procedure pf_arcsin;
Begin
  pr_globals^[OFS_RETURN] := ArcTan (G_FLOAT(OFS_PARM0)/sqrt (1-sqr (G_FLOAT(OFS_PARM0))));
End;

Procedure pf_arccos;
Begin
  pr_globals^[OFS_RETURN] := ArcTan (sqrt (1-sqr (G_FLOAT(OFS_PARM0))) / G_FLOAT(OFS_PARM0));
End;

Procedure pf_arctan;
Begin
  pr_globals^[OFS_RETURN] := ArcTan(G_FLOAT(OFS_PARM0));
End;

{Some more fun TRIG stuff:}
Procedure pf_normalize;
Var vec : vec3_t;
    f   : float;
Begin
  vec := G_VECTOR(OFS_PARM0)^;
  {l = û(xý+yý+zý)}
  {x = x / l}
  {y = y / l}
  {z = z / l}
  f := sqrt( (vec[0] * vec[0]) + (vec[1] * vec[1]) + (vec[2] * vec[2]) );
  f := 1/f;
  vec[0] := f*vec[0];
  vec[1] := f*vec[1];
  vec[2] := f*vec[2];
  SET_G_VECTOR(OFS_RETURN, @vec);
End;

{Can also be used for distance calculations... ex:
   vlen('0 0 10' - '0 0 5') = 5.0}
Procedure pf_vlen;
Var vec : vec3_t;
    f   : float;
Begin
  vec := G_VECTOR(OFS_PARM0)^;
  {len = û(xý+yý+zý)}
  f := sqrt( (vec[0] * vec[0]) + (vec[1] * vec[1]) + (vec[2] * vec[2]) );
  pr_globals^[OFS_RETURN] := f;
End;

End.