IMPLEMENTATION MODULE MathLibLong;
(*$
   LargeVars:=FALSE
   StackChk:=FALSE
   LongAlign:=TRUE
   NilChk:=FALSE
   Volatile:=FALSE
   StackParms:=FALSE
   RangeChk:=FALSE
   ReturnChk:=FALSE
*)

FROM SYSTEM IMPORT ASSEMBLE;
IMPORT	MB:MathIEEEDoubBas,
	Arts,
	ExecD;

(* Prozeduren mit Implementation: *)


(* Ewig Aerger mit Reg D0,D1, nicht direkt compilierbar! *)
(* Deshalb muss das leider komplett in Assembler! *)


PROCEDURE atanh(x{0}:LONGREAL):LONGREAL;
(*$ EntryExitCode:=FALSE *)
BEGIN
  (* RETURN log((x+1.0)/(1.0-x))/2.0; *)
  ASSEMBLE(
    (*$ IF m68881 *) (* doppelte Optimierung *)
	MOVEM.L	D0-D1,-(A7)
	FATANH.D (A7)+,FP0
	FMOVE.D	FP0,-(A7)
	MOVEM.L	(A7)+,D0-D1
    (*$ ELSE *)
	MOVEM.L	D2-D7/A6,-(A7)

	MOVEA.L	MB(A4),A6
	MOVE.L	D0,D4
	MOVE.L	D1,D5	(* sichern *)
	MOVE.L	#$3FF00000,D2
	MOVEQ	#0,D3
	JSR	MB.Add(A6)
	MOVE.L	D0,D6
	MOVE.L	D1,D7

	MOVE.L	D4,D2	(* aendert er D2,D3 oder nicht? *)
	MOVE.L	D5,D3
	MOVE.L	#$3FF00000,D0
	MOVEQ	#0,D1
	JSR	MB.Sub(A6)
	MOVE.L	D0,D2
	MOVE.L	D1,D3
	MOVE.L	D6,D0
	MOVE.L	D7,D1
	JSR	MB.Div(A6)
	MOVEA.L	mathieeedoubtransBase(A4),A6
	JSR	log(A6)

	MOVEA.L	MB(A4),A6
	MOVE.L	#$40000000,D2
	MOVEQ	#0,D3
	JSR	MB.Div(A6)
	MOVEM.L	(A7)+,D2-D7/A6
    (*$ ENDIF *)
	RTS
  END);
END atanh;

PROCEDURE etoxm1(x{0}:LONGREAL):LONGREAL;
(*$ EntryExitCode:=FALSE *)
BEGIN
  (* RETURN exp(x)-1.0; *)
  ASSEMBLE(
    (*$ IF m68881 *)
	MOVEM.L	D0-D1,-(A7)
	FETOXM1.D (A7)+,FP0
	FMOVE.D	FP0,-(A7)
	MOVEM.L	(A7)+,D0-D1
    (*$ ELSE *)
	MOVEM.L	D2/D3/A6,-(A7)
	MOVEA.L mathieeedoubtransBase(A4),A6
	JSR	exp(A6)
	MOVE.L	#$3FF00000,D2
	MOVEQ	#0,D3
	MOVEA.L MB(A4),A6
	JSR	MB.Sub(A6)
	MOVEM.L	(A7)+,D2/D3/A6
    (*$ ENDIF *)
 	RTS
  END);
END etoxm1;

PROCEDURE log2(x{0}:LONGREAL):LONGREAL;
(*$ EntryExitCode:=FALSE *)
BEGIN
  (* RETURN log(x)/log(2.0); *)
  ASSEMBLE(
    (*$ IF m68881 *)
	MOVEM.L	D0-D1,-(A7)
	FLOG2.D	(A7)+,FP0
	FMOVE.D	FP0,-(A7)
	MOVEM.L	(A7)+,D0-D1
    (*$ ELSE *)
	MOVEM.L	D2/D3/A6,-(A7)
	MOVEA.L	mathieeedoubtransBase(A4),A6
	JSR	log(A6)
	MOVE.L	D0,D2
	MOVE.L	D1,D3
	MOVE.L	#$40000000,D0
	MOVEQ	#0,D1
	JSR	log(A6)
	EXG	D0,D2
	EXG	D1,D3
	MOVEA.L	MB(A4),A6
	JSR	MB.Div(A6)
	MOVEM.L	(A7)+,D2/D3/A6
    (*$ ENDIF *)
 	RTS
  END);
END log2;

PROCEDURE lognp1(x{0}:LONGREAL):LONGREAL;
(*$ EntryExitCode:=FALSE *)
BEGIN
  (* RETURN log(x+1.0); *)
  ASSEMBLE(
    (*$ IF m68881 *)
	MOVEM.L	D0-D1,-(A7)
	FLOGNP1.D (A7)+,FP0
	FMOVE.D	FP0,-(A7)
	MOVEM.L	(A7)+,D0-D1
    (*$ ELSE *)
	MOVEM.L	D2/D3/A6,-(A7)
	MOVE.L	#$3FF00000,D2
	MOVEQ	#0,D3
	MOVEA.L MB(A4),A6
	JSR	MB.Add(A6)
	MOVEA.L mathieeedoubtransBase(A4),A6
	JSR	log(A6)
	MOVEM.L	(A7)+,D2/D3/A6
    (*$ ENDIF *)
 	RTS
  END);
END lognp1;

PROCEDURE tentox(x{0}:LONGREAL):LONGREAL;
(*$ EntryExitCode:=FALSE *)
BEGIN
  (* RETURN pow(10.0,x); *)
  ASSEMBLE(
    (*$ IF m68881 *)
	MOVEM.L	D0-D1,-(A7)
	FTENTOX.D (A7)+,FP0
	FMOVE.D	FP0,-(A7)
	MOVEM.L	(A7)+,D0-D1
    (*$ ELSE *)
	MOVEM.L	D2/D3/A6,-(A7)
	MOVE.L	D0,D2
	MOVE.L	D1,D3
	MOVE.L	#$40240000,D0
	MOVEQ	#0,D1
	MOVEA.L	mathieeedoubtransBase(A4),A6
	JSR	pow(A6)
	MOVEM.L	(A7)+,D2/D3/A6
    (*$ ENDIF *)
 	RTS
  END);
END tentox;

PROCEDURE twotox(x{0}:LONGREAL):LONGREAL;
(*$ EntryExitCode:=FALSE *)
BEGIN
  (* RETURN pow(2.0,x); *)
  ASSEMBLE(
    (*$ IF m68881 *)
	MOVEM.L	D0-D1,-(A7)
	FTWOTOX.D (A7)+,FP0
	FMOVE.D	FP0,-(A7)
	MOVEM.L	(A7)+,D0-D1
    (*$ ELSE *)
	MOVEM.L	D2/D3/A6,-(A7)
	MOVE.L	D0,D2
	MOVE.L	D1,D3
	MOVE.L	#$40000000,D0
	MOVEQ	#0,D1
	MOVEA.L	mathieeedoubtransBase(A4),A6
	JSR	pow(A6)
	MOVEM.L	(A7)+,D2/D3/A6
    (*$ ENDIF *)
 	RTS
  END);
END twotox;

PROCEDURE sqr(x{0}:LONGREAL):LONGREAL;
BEGIN
  RETURN x*x;
END sqr;


BEGIN
  ASSEMBLE(
	MOVEQ	#mathieeedoubtransMinVersion,D0
	LEA	mathieeedoubtransName(PC),A1
	JSR	Arts.OpenLib(PC)
	MOVE.L	D0,mathieeedoubtransBase(A4)
	MOVE.L	D0,A0
	MOVE.W	ExecD.Library.version(A0),mathieeedoubtransVersion(A4)
  END);
CLOSE
  (* Arts kann auch NIL vertragen! *)
  Arts.CloseLib(mathieeedoubtransBase);
END MathLibLong.mod
