383 lines
12 KiB
Ada
383 lines
12 KiB
Ada
--
|
||
-- MATH.ADA
|
||
--
|
||
-- Mathematical routines for Artek Ada
|
||
--
|
||
-- Package body Copyright (C) 1986 Artek Corporation
|
||
-- Author: V. Thorsteinsson
|
||
--
|
||
-- The MATH package offers common exponential, logarithmic,
|
||
-- trigonometric and hyperbolic functions used in mathematical
|
||
-- calculation.
|
||
--
|
||
-- Most routines are implemented in assembly language for maximum
|
||
-- speed and accuracy. An 8087/287/387 coprocessor is used if
|
||
-- present and emulated in software if not.
|
||
--
|
||
-- The routines raise the exception ARGUMENT_ERROR if their
|
||
-- arguments are out of bounds.
|
||
--
|
||
-- The trigonometric functions can accept an optional CYCLE parameter
|
||
-- that allows you to work in degrees or grads if you prefer them to
|
||
-- radians. In this case, say for example:
|
||
--
|
||
-- A := SIN (90.0, CYCLE => 360.0);
|
||
--
|
||
-- to calculate the sine of a 90 degree angle.
|
||
--
|
||
|
||
generic
|
||
|
||
type REAL is digits <>;
|
||
|
||
package MATH is
|
||
|
||
PI : constant := 3.1415_92653_58979_32384_62643_38327_95029;
|
||
EXP_1 : constant := 2.7182_81828_45904_52353_60287_47135_26625;
|
||
|
||
function SQRT (X : REAL) return REAL;
|
||
function LOG (X : REAL; BASE : REAL := EXP_1) return REAL;
|
||
function EXP (X : REAL; BASE : REAL := EXP_1) return REAL;
|
||
function SIN (X : REAL; CYCLE : REAL := 2.0 * PI) return REAL;
|
||
function COS (X : REAL; CYCLE : REAL := 2.0 * PI) return REAL;
|
||
function TAN (X : REAL; CYCLE : REAL := 2.0 * PI) return REAL;
|
||
function COT (X : REAL; CYCLE : REAL := 2.0 * PI) return REAL;
|
||
function ARCSIN (X : REAL) return REAL;
|
||
function ARCCOS (X : REAL) return REAL;
|
||
function ARCTAN (X : REAL; Y : REAL := 1.0) return REAL;
|
||
function ARCCOT (X : REAL; Y : REAL := 1.0) return REAL;
|
||
function SINH (X : REAL) return REAL;
|
||
function COSH (X : REAL) return REAL;
|
||
function TANH (X : REAL) return REAL;
|
||
function COTH (X : REAL) return REAL;
|
||
function ARCSINH (X : REAL) return REAL;
|
||
function ARCCOSH (X : REAL) return REAL;
|
||
function ARCTANH (X : REAL) return REAL;
|
||
function ARCCOTH (X : REAL) return REAL;
|
||
|
||
ARGUMENT_ERROR : exception;
|
||
|
||
end MATH;
|
||
|
||
package body MATH is
|
||
|
||
function "rem" (LEFT, RIGHT : REAL) return REAL is
|
||
RESULT : REAL;
|
||
STATUS : INTEGER;
|
||
begin
|
||
pragma NATIVE (
|
||
16#CD#, 16#39#, 16#44#, 16#08#, 16#CD#, 16#39#, 16#04#, 16#CD#,
|
||
16#35#, 16#E4#, 16#33#, 16#C9#, 16#CD#, 16#39#, 16#7D#, 16#08#,
|
||
16#CD#, 16#3D#, 16#8B#, 16#45#, 16#08#, 16#9E#, 16#73#, 16#05#,
|
||
16#CD#, 16#35#, 16#E0#, 16#F7#, 16#D1#, 16#CD#, 16#35#, 16#F8#,
|
||
16#CD#, 16#39#, 16#7D#, 16#08#, 16#CD#, 16#3D#, 16#8B#, 16#45#,
|
||
16#08#, 16#9E#, 16#7A#, 16#F1#, 16#CD#, 16#39#, 16#D9#, 16#23#,
|
||
16#C9#, 16#74#, 16#03#, 16#CD#, 16#35#, 16#E0#, 16#CD#, 16#39#,
|
||
16#1D#, 16#CD#, 16#3D#);
|
||
return RESULT;
|
||
end "rem";
|
||
|
||
function MYTAN (X : REAL) return REAL is
|
||
RESULT : REAL;
|
||
PIOVER4 : REAL := PI / 4.0;
|
||
PIOVER2 : REAL := PI / 2.0;
|
||
STATUS_WORD : INTEGER;
|
||
ENVIRONMENT : array (1..8) of INTEGER;
|
||
begin
|
||
pragma NATIVE (
|
||
16#CD#, 16#35#, 16#EB#, 16#CD#, 16#39#, 16#04#, 16#CD#, 16#35#,
|
||
16#E4#, 16#33#, 16#DB#, 16#8B#, 16#CB#, 16#CD#, 16#39#, 16#7D#,
|
||
16#18#, 16#CD#, 16#3D#, 16#8B#, 16#45#, 16#18#, 16#9E#, 16#73#,
|
||
16#05#, 16#CD#, 16#35#, 16#E0#, 16#F7#, 16#D1#, 16#CD#, 16#35#,
|
||
16#F8#, 16#CD#, 16#39#, 16#7D#, 16#18#, 16#CD#, 16#3D#, 16#8B#,
|
||
16#45#, 16#18#, 16#9E#, 16#7A#, 16#F1#, 16#CD#, 16#39#, 16#D9#,
|
||
16#CD#, 16#39#, 16#45#, 16#10#, 16#CD#, 16#35#, 16#C9#, 16#CD#,
|
||
16#34#, 16#D1#, 16#CD#, 16#39#, 16#7D#, 16#18#, 16#CD#, 16#3D#,
|
||
16#8B#, 16#45#, 16#18#, 16#9E#, 16#76#, 16#07#, 16#CD#, 16#34#,
|
||
16#E1#, 16#F7#, 16#D3#, 16#F7#, 16#D1#, 16#CD#, 16#39#, 16#45#,
|
||
16#08#, 16#CD#, 16#34#, 16#D9#, 16#CD#, 16#39#, 16#7D#, 16#18#,
|
||
16#CD#, 16#3D#, 16#8B#, 16#45#, 16#18#, 16#9E#, 16#73#, 16#05#,
|
||
16#CD#, 16#34#, 16#E9#, 16#F7#, 16#D3#, 16#CD#, 16#39#, 16#D9#,
|
||
16#CD#, 16#35#, 16#F2#, 16#23#, 16#C9#, 16#74#, 16#03#, 16#CD#,
|
||
16#35#, 16#E0#, 16#23#, 16#DB#, 16#74#, 16#05#, 16#CD#, 16#3A#,
|
||
16#F1#, 16#EB#, 16#03#, 16#CD#, 16#3A#, 16#F9#, 16#CD#, 16#39#,
|
||
16#1D#, 16#CD#, 16#3D#);
|
||
return RESULT;
|
||
end MYTAN;
|
||
|
||
function MYCOT (X : REAL) return REAL is
|
||
-- Cotangent with no checking
|
||
begin
|
||
return 1.0 / MYTAN (X);
|
||
end MYCOT;
|
||
|
||
function SQRT (X : REAL) return REAL is
|
||
RESULT : REAL;
|
||
begin
|
||
if X < 0.0 then
|
||
raise ARGUMENT_ERROR;
|
||
end if;
|
||
pragma NATIVE (
|
||
16#CD#, 16#39#, 16#04#, 16#CD#, 16#35#, 16#FA#, 16#CD#, 16#39#,
|
||
16#1D#, 16#CD#, 16#3D#);
|
||
return RESULT;
|
||
end SQRT;
|
||
|
||
function LN (X : REAL) return REAL is
|
||
RESULT : REAL;
|
||
begin
|
||
pragma NATIVE (
|
||
16#CD#, 16#35#, 16#ED#, 16#CD#, 16#39#, 16#04#, 16#CD#, 16#35#,
|
||
16#F1#, 16#CD#, 16#39#, 16#1D#, 16#CD#, 16#3D#);
|
||
return RESULT;
|
||
end LN;
|
||
|
||
function LOG (X : REAL; BASE : REAL := EXP_1) return REAL is
|
||
begin
|
||
if X <= 0.0 or BASE <= 0.0 or BASE = 1.0 then
|
||
raise ARGUMENT_ERROR;
|
||
end if;
|
||
if BASE = EXP_1 then
|
||
return LN (X);
|
||
else
|
||
return LN (X) / LN (BASE);
|
||
end if;
|
||
end LOG;
|
||
|
||
function EXPONENTIAL (X : REAL) return REAL is
|
||
RESULT : REAL;
|
||
STATUS : INTEGER;
|
||
begin
|
||
pragma NATIVE (
|
||
16#CD#, 16#39#, 16#04#, 16#CD#, 16#35#, 16#EA#, 16#CD#, 16#3A#,
|
||
16#C9#, 16#CD#, 16#35#, 16#C0#, 16#CD#, 16#35#, 16#FC#, 16#CD#,
|
||
16#35#, 16#C0#, 16#CD#, 16#34#, 16#EA#, 16#CD#, 16#35#, 16#E4#,
|
||
16#CD#, 16#39#, 16#7D#, 16#08#, 16#CD#, 16#3D#, 16#8B#, 16#45#,
|
||
16#08#, 16#9E#, 16#CD#, 16#35#, 16#E1#, 16#CD#, 16#35#, 16#F0#,
|
||
16#CD#, 16#35#, 16#E8#, 16#CD#, 16#3A#, 16#C1#, 16#73#, 16#06#,
|
||
16#CD#, 16#35#, 16#E8#, 16#CD#, 16#3A#, 16#F1#, 16#CD#, 16#35#,
|
||
16#FD#, 16#CD#, 16#39#, 16#1D#, 16#CD#, 16#39#, 16#D8#, 16#CD#,
|
||
16#39#, 16#D8#);
|
||
return RESULT;
|
||
end EXPONENTIAL;
|
||
|
||
function EXP (X : REAL; BASE : REAL := EXP_1) return REAL is
|
||
begin
|
||
if BASE <= 0.0 then
|
||
raise ARGUMENT_ERROR;
|
||
end if;
|
||
if BASE = EXP_1 then
|
||
return EXPONENTIAL (X);
|
||
else
|
||
return EXPONENTIAL (X * LN (BASE));
|
||
end if;
|
||
end EXP;
|
||
|
||
function SIN (X : REAL; CYCLE : REAL := 2.0 * PI) return REAL is
|
||
CT : REAL;
|
||
TX : REAL;
|
||
begin
|
||
if CYCLE = 0.0 then
|
||
raise ARGUMENT_ERROR;
|
||
end if;
|
||
TX := (X / CYCLE) * 2.0 * PI;
|
||
TX := TX rem (2.0 * PI); -- Floating-point remainder
|
||
if (TX = 0.0) or (TX = PI) then -- Avoid division by zero
|
||
return 0.0;
|
||
else
|
||
CT := MYCOT (TX / 2.0); -- Argument has already been checked
|
||
return (2.0 * CT) / (1.0 + CT * CT);
|
||
end if;
|
||
end SIN;
|
||
|
||
function COS (X : REAL; CYCLE : REAL := 2.0 * PI) return REAL is
|
||
CT : REAL;
|
||
TX : REAL;
|
||
begin
|
||
if CYCLE = 0.0 then
|
||
raise ARGUMENT_ERROR;
|
||
end if;
|
||
TX := (X / CYCLE) * 2.0 * PI;
|
||
TX := TX rem (2.0 * PI);
|
||
if (TX = 0.0) or (TX = PI) then -- Avoid division by zero
|
||
return 1.0;
|
||
else
|
||
CT := MYCOT (TX / 2.0); -- Argument has already been checked
|
||
return - (1.0 - CT * CT) / (1.0 + CT * CT);
|
||
end if;
|
||
end COS;
|
||
|
||
function TAN (X : REAL; CYCLE : REAL := 2.0 * PI) return REAL is
|
||
|
||
TX : REAL;
|
||
|
||
begin
|
||
if CYCLE = 0.0 then
|
||
raise ARGUMENT_ERROR;
|
||
end if;
|
||
TX := (X / CYCLE) * 2.0 * PI;
|
||
TX := TX rem (2.0 * PI);
|
||
return MYTAN (TX);
|
||
end TAN;
|
||
|
||
function COT (X : REAL; CYCLE : REAL := 2.0 * PI) return REAL is
|
||
begin
|
||
return 1.0 / TAN (X, CYCLE);
|
||
end COT;
|
||
|
||
function ARCSIN (X : REAL) return REAL is
|
||
begin
|
||
if abs X > 1.0 then
|
||
raise ARGUMENT_ERROR;
|
||
end if;
|
||
return ARCTAN (X / SQRT ((1.0 - X) * (1.0 + X)));
|
||
end ARCSIN;
|
||
|
||
function ARCCOS (X : REAL) return REAL is
|
||
begin
|
||
if abs X > 1.0 then
|
||
raise ARGUMENT_ERROR;
|
||
end if;
|
||
return 2.0 * ARCTAN (SQRT ((1.0 - X) / (1.0 + X)));
|
||
end ARCCOS;
|
||
|
||
function ARCTAN (X : REAL; Y : REAL := 1.0) return REAL is
|
||
|
||
PIOVER2 : constant REAL := PI / 2.0;
|
||
|
||
function ATAN (X, Y : in REAL) return REAL is
|
||
RESULT : REAL;
|
||
begin
|
||
pragma NATIVE (
|
||
16#CD#, 16#39#, 16#04#, 16#CD#, 16#39#, 16#44#, 16#08#, 16#CD#,
|
||
16#35#, 16#F3#, 16#CD#, 16#39#, 16#1D#, 16#CD#, 16#3D#);
|
||
return RESULT;
|
||
end ATAN;
|
||
|
||
begin
|
||
if X = 0.0 and Y = 0.0 then
|
||
raise ARGUMENT_ERROR;
|
||
end if;
|
||
if X / Y < 0.0 then
|
||
return - ARCTAN (-X, Y);
|
||
elsif X > Y then
|
||
return PIOVER2 - ATAN (Y, X);
|
||
else
|
||
return ATAN (X, Y);
|
||
end if;
|
||
end ARCTAN;
|
||
|
||
function ARCCOT (X : REAL; Y : REAL := 1.0) return REAL is
|
||
begin
|
||
return ARCTAN (Y, X);
|
||
end ARCCOT;
|
||
|
||
function SINH (X : REAL) return REAL is
|
||
EABSX : constant REAL := EXP (abs X);
|
||
RESULT : REAL;
|
||
begin
|
||
RESULT := 0.5 * (EABSX - 1.0 + (EABSX - 1.0) / EABSX);
|
||
if X >= 0.0 then
|
||
return RESULT;
|
||
else
|
||
return - RESULT;
|
||
end if;
|
||
end SINH;
|
||
|
||
function COSH (X : REAL) return REAL is
|
||
EABSX : constant REAL := EXP (abs X);
|
||
begin
|
||
return 0.5 * (EABSX + 1.0 / EABSX);
|
||
end COSH;
|
||
|
||
function TANH (X : REAL) return REAL is
|
||
E2ABSX : constant REAL := EXP (2.0 * abs X);
|
||
RESULT : REAL;
|
||
begin
|
||
RESULT := (E2ABSX - 1.0) / (E2ABSX + 1.0);
|
||
if X >= 0.0 then
|
||
return RESULT;
|
||
else
|
||
return - RESULT;
|
||
end if;
|
||
end TANH;
|
||
|
||
function COTH (X : REAL) return REAL is
|
||
begin
|
||
return 1.0 / TANH (X);
|
||
end COTH;
|
||
|
||
function ARCSINH (X : REAL) return REAL is
|
||
|
||
ABSX : constant REAL := abs X;
|
||
|
||
function ASINH (X : REAL) return REAL is
|
||
SIGNX : constant INTEGER := INTEGER (X / ABSX);
|
||
Z : constant REAL :=
|
||
ABSX + ABSX / (1.0 / ABSX + SQRT (1.0 + (1.0 / ABSX / ABSX)));
|
||
RESULT : REAL;
|
||
begin
|
||
pragma NATIVE (
|
||
16#CD#, 16#3B#, 16#05#, 16#CD#, 16#35#, 16#ED#, 16#CD#, 16#3A#,
|
||
16#C9#, 16#CD#, 16#39#, 16#45#, 16#02#, 16#CD#, 16#35#, 16#E8#,
|
||
16#CD#, 16#3A#, 16#C1#, 16#CD#, 16#35#, 16#F1#, 16#CD#, 16#39#,
|
||
16#5D#, 16#0A#, 16#CD#, 16#3D#);
|
||
return RESULT;
|
||
end ASINH;
|
||
|
||
begin
|
||
return ASINH (X);
|
||
end ARCSINH;
|
||
|
||
function ARCCOSH (X : REAL) return REAL is
|
||
|
||
function ACOSH (X : REAL) return REAL is
|
||
Z : constant REAL := X + SQRT ((X - 1.0) * (X + 1.0));
|
||
RESULT : REAL;
|
||
begin
|
||
pragma NATIVE (
|
||
16#CD#, 16#35#, 16#ED#, 16#CD#, 16#39#, 16#05#, 16#CD#, 16#35#,
|
||
16#F1#, 16#CD#, 16#39#, 16#5D#, 16#08#, 16#CD#, 16#3D#);
|
||
return RESULT;
|
||
end ACOSH;
|
||
|
||
begin
|
||
if X < 1.0 then
|
||
raise ARGUMENT_ERROR;
|
||
end if;
|
||
return ACOSH (X);
|
||
end ARCCOSH;
|
||
|
||
function ARCTANH (X : REAL) return REAL is
|
||
|
||
ABSX : constant REAL := abs X;
|
||
|
||
function ATANH (X : REAL) return REAL is
|
||
SIGNX : constant INTEGER := INTEGER (X / ABSX);
|
||
Z : constant REAL := 2.0 * ABSX / (1.0 - ABSX);
|
||
RESULT : REAL;
|
||
begin
|
||
pragma NATIVE (
|
||
16#CD#, 16#3B#, 16#05#, 16#CD#, 16#35#, 16#ED#, 16#CD#, 16#3A#,
|
||
16#C9#, 16#CD#, 16#39#, 16#45#, 16#02#, 16#CD#, 16#35#, 16#E8#,
|
||
16#CD#, 16#3A#, 16#C1#, 16#CD#, 16#35#, 16#F1#, 16#CD#, 16#39#,
|
||
16#5D#, 16#0A#, 16#CD#, 16#3D#);
|
||
return RESULT / 2.0;
|
||
end ATANH;
|
||
|
||
begin
|
||
if abs X >= 1.0 then
|
||
raise ARGUMENT_ERROR;
|
||
end if;
|
||
return ATANH (X);
|
||
end ARCTANH;
|
||
|
||
function ARCCOTH (X : REAL) return REAL is
|
||
begin
|
||
return ARCTANH (1.0 / X);
|
||
end ARCCOTH;
|
||
|
||
end MATH;
|
||
|
||
|
||
|