home *** CD-ROM | disk | FTP | other *** search
/ Programmer's ROM - The Computer Language Library / programmersrom.iso / ada / math / mlib2.src < prev    next >
Encoding:
Text File  |  1988-05-03  |  46.2 KB  |  1,646 lines

  1. ,print 106
  2. type 86 86 86 86
  3. ,end
  4. package FLOATING_CHARACTERISTICS is
  5. --  This package is a floating mantissa definition of a binary FLOAT 
  6. --  It was first used on the DEC-10 and the VAX but should work for any
  7. --  since the parameters are obtained by initializing on the actual hardware
  8. --  Otherwise the parameters could be set in the spec if known
  9. --  This is a preliminary package that defines the properties 
  10. --  of the particular floating point type for which we are going to
  11. --  generate the math routines
  12. --  The constants are those required by the routines described in
  13. --  "Software Manual for the Elementary Functions" W. Cody & W. Waite
  14. --  Prentice-Hall 1980
  15. --  Actually most are needed only for the test programs
  16. --  rather than the functions themselves, but might as well be here
  17. --  Most of these could be in the form of attributes if 
  18. --  all the floating types to be considered were those built into the
  19. --  compiler, but we also want to be able to support user defined types
  20. --  such as software floating types of greater precision than
  21. --  the hardware affords, or types defined on one machine to
  22. --  simulate another
  23. --  So we use the Cody-Waite names and derive them from an adaptation of the
  24. --  MACHAR routine as given by Cody-Waite in Appendix B
  25.  
  26.     IBETA : INTEGER;
  27.     --  The radix of the floating-point representation
  28.  
  29.     IT : INTEGER;
  30.     --  The number of base IBETA digits in the DIS_FLOAT significand
  31.  
  32.     IRND : INTEGER;
  33.     --  TRUE (1) if floating addition rounds, FALSE (0) if truncates
  34.  
  35.     NGRD : INTEGER;
  36.     --  Number of guard digits for multiplication
  37.  
  38.     MACHEP : INTEGER;
  39.     --  The largest negative integer such that
  40.     --    1.0 + FLOAT(IBETA) ** MACHEP /= 1.0
  41.     --  except that MACHEP is bounded below by -(IT + 3)
  42.  
  43.     NEGEP : INTEGER;
  44.     --  The largest negative integer such that
  45.     --    1.0 -0 FLOAT(IBETA) ** NEGEP /= 1.0
  46.     --  except that NEGEP is bounded below by -(IT + 3)
  47.  
  48.     IEXP : INTEGER;
  49.     --  The number of bits (decimal places if IBETA = 10)
  50.     --  reserved for the representation of the exponent (including
  51.     --  the bias or sign) of a floating-point number
  52.  
  53.     MINEXP : INTEGER;
  54.     --  The largest in magnitude negative integer such that
  55.     --  FLOAT(IBETA) ** MINEXP is a positive floating-point number
  56.  
  57.  
  58.     MAXEXP : INTEGER;
  59.     --  The largest positive exponent for a finite floating-point number
  60.  
  61.     EPS : FLOAT;
  62.     --  The smallest positive floating-point number such that
  63.     --                              1.0 + EPS /= 1.0
  64.     --  In particular, if IBETA = 2 or IRND = 0,
  65.     --  EPS = FLOAT(IBETA) ** MACHEP
  66.     --  Otherwise, EPS = (FLOAT(IBETA) ** MACHEP) / 2
  67.  
  68.  
  69.     EPSNEG : FLOAT;
  70.     --  A small positive floating-point number such that 1.0-EPSNEG /= 1.0
  71.  
  72.     XMIN : FLOAT;
  73.     --  The smallest non-vanishing floating-point power of the radix
  74.     --  In particular, XMIN = FLOAT(IBETA) ** MINEXP
  75.  
  76.     XMAX : FLOAT;
  77.     --  The largest finite floating-point number
  78.  
  79. --  Here the structure of the floating type is defined
  80. --  I have assumed that the exponent is always some integer form
  81. --  The mantissa can vary
  82. --  Most often it will be a fixed type or the same floating type
  83. --  depending on the most efficient machine implementation
  84. --  Most efficient implementation may require details of the machine hardware
  85. --  In this version the simplest representation is used
  86. --  The mantissa is extracted into a FLOAT and uses the predefined operations
  87.   subtype EXPONENT_TYPE is INTEGER;    --  should be derived  ##########
  88.   subtype MANTISSA_TYPE is FLOAT;     --   range -1.0..1.0;
  89. --  A consequence of the rigorous constraints on MANTISSA_TYPE is that 
  90. --  operations must be very carefully examined to make sure that no number
  91. --  greater than one results
  92. --  Actually this limitation is important in constructing algorithms
  93. --  which will also run when MANTISSA_TYPE is a fixed point type
  94.  
  95. --  If we are not using the STANDARD type, we have to define all the 
  96. --  operations at this point
  97. --  We also need PUT for the type if it is not otherwise available
  98.  
  99. --  Now we do something strange
  100. --  Since we do not know in the following routines whether the mantissa
  101. --  will be carried as a fixed or floating type, we have to make some
  102. --  provision for dividing by two
  103. --  We cannot use the literals, since FIXED/2.0 and FLOAT/2 will fail
  104. --  We define a type-dependent factor that will work
  105.   MANTISSA_DIVISOR_2 : constant FLOAT := 2.0;
  106.   MANTISSA_DIVISOR_3 : constant FLOAT := 3.0;
  107. --  This will work for the MANTISSA_TYPE defined above
  108. --  The alternative of defining an operation "/" to take care of it
  109. --  is too sweeping and would allow unAda-like errors
  110.  
  111.   MANTISSA_HALF : constant MANTISSA_TYPE := 0.5;
  112.  
  113.  
  114.   procedure DEFLOAT(X : in FLOAT;
  115.                     L : out EXPONENT_TYPE; E : out MANTISSA_TYPE);
  116.   procedure REFLOAT(N : in EXPONENT_TYPE; F : in MANTISSA_TYPE; 
  117.                                                    Z : out FLOAT);
  118. --  Since the user may wish to define a floating type by some other name
  119. --  CONVERT_TO_FLOAT is used rather than just FLOAT for explicit coersion
  120.   function CONVERT_TO_FLOAT(K : INTEGER) return FLOAT;
  121.   --function CONVERT_TO_FLOAT(N : EXPONENT_TYPE) return FLOAT;
  122.   function CONVERT_TO_FLOAT(F : MANTISSA_TYPE) return FLOAT;
  123.  
  124. end FLOATING_CHARACTERISTICS;
  125.  
  126. with FLOATING_CHARACTERISTICS;
  127. use FLOATING_CHARACTERISTICS;
  128. package NUMERIC_PRIMITIVES is
  129.  
  130.   --  This may seem a little much but is put in this form to allow the
  131.   --  same form to be used for a generic package
  132.   --  If that is not needed, simple litterals could be substituted
  133.   ZERO  : FLOAT;
  134.   ONE   : FLOAT;
  135.   TWO   : FLOAT;
  136.   THREE : FLOAT;
  137.   HALF  : FLOAT;
  138.  
  139.   --  The following "constants" are effectively deferred to
  140.   --  the initialization part of the package body
  141.   --  This is in order to make it possible to generalize the floating type
  142.   --  If that capability is not desired, constants may be included here
  143.   PI            : FLOAT;
  144.   ONE_OVER_PI   : FLOAT;
  145.   TWO_OVER_PI   : FLOAT;
  146.   PI_OVER_TWO   : FLOAT;
  147.   PI_OVER_THREE : FLOAT;
  148.   PI_OVER_FOUR  : FLOAT;
  149.   PI_OVER_SIX   : FLOAT;
  150.  
  151.  
  152.   function SIGN(X, Y : FLOAT) return FLOAT;
  153.     --  Returns the value of X with the sign of Y
  154.   function MAX(X, Y :  FLOAT) return FLOAT;
  155.     --  Returns the algebraicly larger of X and Y
  156.   function TRUNCATE(X : FLOAT) return FLOAT;
  157.     --  Returns the floating value of the integer no larger than X
  158.     --  AINT(X)
  159.   function ROUND(X : FLOAT) return FLOAT;
  160.     --  Returns the floating value nearest X
  161.     --  AINTRND(X)
  162.   function RAN return FLOAT;
  163.     --  This uses a portable algorithm and is included at this point
  164.     --  Algorithms that presume unique machine hardware information
  165.     --  should be initiated in FLOATING_CHARACTERISTICS
  166.  
  167. end NUMERIC_PRIMITIVES;
  168.  
  169. with FLOATING_CHARACTERISTICS;
  170. use FLOATING_CHARACTERISTICS;
  171. package CORE_FUNCTIONS is
  172.  
  173.   EXP_LARGE : FLOAT;
  174.   EXP_SMALL : FLOAT;
  175.  
  176.   function SQRT(X : FLOAT) return FLOAT;
  177.   function CBRT(X : FLOAT) return FLOAT;
  178.   function LOG(X : FLOAT) return FLOAT;
  179.   function LOG10(X : FLOAT) return FLOAT;
  180.   function EXP(X : FLOAT) return FLOAT;
  181.   function "**"(X, Y : FLOAT) return FLOAT;
  182.  
  183. end CORE_FUNCTIONS;
  184.  
  185. package body FLOATING_CHARACTERISTICS is
  186. --  This package is a floating mantissa definition of a binary FLOAT
  187.  
  188.     A, B, Y, Z : FLOAT;
  189.     I, K, MX, IZ : INTEGER;
  190.     BETA, BETAM1, BETAIN : FLOAT;
  191.     ONE : FLOAT := 1.0;
  192.     ZERO : FLOAT := 0.0;
  193.  
  194.   procedure DEFLOAT(X : in FLOAT;
  195.                     L : out EXPONENT_TYPE; E : out MANTISSA_TYPE) is
  196. --  This is admittedly a slow method - but portable - for breaking down
  197. --  a floating point number into its exponent and mantissa
  198. --  Obviously with knowledge of the machine representation
  199. --  it could be replaced with a couple of simple extractions
  200.     EXPONENT_LENGTH : INTEGER := IEXP;
  201.     M, N : EXPONENT_TYPE;
  202.     W, Y, Z : FLOAT;
  203.     F : MANTISSA_TYPE;
  204.   begin
  205.     N := 0;
  206.     F := 0.0;
  207.     Y := ABS(X);
  208.     if Y = 0.0  then
  209.       return;
  210.     elsif Y < 0.5  then
  211.       for J in reverse 0..(EXPONENT_LENGTH - 2)  loop
  212.       --  Dont want to go all the way to 2.0**(EXPONENT_LENGTH - 1)
  213.       --  Since that (or its reciprocal) will overflow if exponent biased
  214.       --  Ought to use talbular values rather than compute each time
  215.         M := EXPONENT_TYPE(2 ** J);
  216.         Z := 1.0 / (2.0**M);
  217.         W := Y / Z;
  218.         if W < 1.0  then
  219.           Y := W;
  220.           N := N - M;
  221.         end if;
  222.       end loop;
  223.     else
  224.       for J in reverse 0..(EXPONENT_LENGTH - 2)  loop
  225.         M := EXPONENT_TYPE(2 ** J);
  226.         Z := 2.0**M;
  227.         W := Y / Z;
  228.         if W >= 0.5  then
  229.           Y := W;
  230.           N := N + M;
  231.         end if;
  232.       end loop;
  233.     --  And just to clear up any loose ends from biased exponents
  234.     end if;
  235.     while Y < 0.5  loop
  236.       Y := Y * 2.0;
  237.       N := N - 1;
  238.     end loop;
  239.     while Y >= 1.0  loop
  240.       Y := Y / 2.0;
  241.       N := N + 1;
  242.     end loop;
  243.     F := MANTISSA_TYPE(Y);
  244.     if X < 0.0  then
  245.       F := -F;
  246.     end if;
  247.     L := N;
  248.     E := F; 
  249.     return;
  250.   exception
  251.   when others =>
  252.     L := 0;
  253.     E := 0.0;
  254.     return;
  255.   end DEFLOAT;
  256.  
  257.  
  258.   procedure REFLOAT(N : in EXPONENT_TYPE; F : in MANTISSA_TYPE; 
  259.                                                    Z : out FLOAT) is
  260. --  Again a brute force method - but portable
  261. --  Watch out near MAXEXP
  262.     M : INTEGER;
  263.     X, Y : FLOAT;
  264.   begin
  265.     if F = 0.0  then
  266.       X := ZERO;
  267.       return;
  268.     end if;
  269.     M := INTEGER(N);
  270.     Y := ABS(FLOAT(F));
  271.     while Y < 0.5  loop
  272.       M := M - 1;
  273.       if M < MINEXP  then
  274.         X := ZERO;
  275.       end if;
  276.       Y := Y + Y;
  277.       exit when M <= MINEXP;
  278.     end loop;
  279.     if M = MAXEXP  then
  280.       M := M - 1;
  281.       X := Y * 2.0**M;
  282.       X := X * 2.0;
  283.     elsif M <= MINEXP + 2  then
  284.       M := M + 3;
  285.       X := Y * 2.0**M;
  286.       X := ((X / 2.0) / 2.0) / 2.0;
  287.     else
  288.       X := Y * 2.0**M;
  289.     end if;
  290.     if F < 0.0  then
  291.       X := -X;
  292.     end if;
  293.     Z := X;
  294.     return;
  295.   end REFLOAT;
  296.  
  297.   function CONVERT_TO_FLOAT(K : INTEGER) return FLOAT is
  298.   begin
  299.     return FLOAT(K);
  300.   end CONVERT_TO_FLOAT;
  301.  
  302.   --function CONVERT_TO_FLOAT(N : EXPONENT_TYPE) return FLOAT is
  303.   --begin
  304.     --return FLOAT(N);
  305.  --end CONVERT_TO_FLOAT;
  306.  
  307.   function CONVERT_TO_FLOAT(F : MANTISSA_TYPE) return FLOAT is
  308.   begin
  309.     return FLOAT(F);
  310.   end CONVERT_TO_FLOAT;
  311.  
  312.  
  313. begin
  314. --  Initialization for the VAX with values derived by MACHAR
  315. --  In place of running MACHAR as the actual initialization
  316.  
  317.     IBETA :=    2;
  318.     IT :=    24;
  319.     IRND :=    1;
  320.     NEGEP :=    -24;
  321.     EPSNEG :=    5.9604644E-008;
  322.     MACHEP :=    -24;
  323.     EPS :=    5.9604644E-008;
  324.     NGRD :=    0;
  325.     XMIN := 5.9E-39;
  326.     MINEXP :=    -126;
  327.     IEXP :=    8;
  328.     MAXEXP :=    127;
  329.     XMAX :=    8.5E37 * 2.0;
  330.  
  331.  
  332. ----  This initialization is the MACHAR routine of Cody and Waite Appendix B.
  333. --PUT("INITIALIZATING WITH MACHAR     -     ");
  334. --    A := ONE;
  335. --    while (((A + ONE) - A) - ONE) = ZERO  loop
  336. --      A := A + A;
  337. --    end loop;
  338. --    B := ONE;
  339. --    while ((A + B) - A) = ZERO  loop
  340. --      B := B + B;
  341. --    end loop;
  342. --    IBETA := INTEGER((A + B) - A);
  343. --    BETA := CONVERT_TO_FLOAT(IBETA);
  344. --
  345. --
  346. --    IT := 0;
  347. --    B := ONE;
  348. --    while (((B + ONE) - B) - ONE) = ZERO  loop
  349. --      IT := IT + 1;
  350. --      B := B * BETA;
  351. --    end loop;
  352. --
  353. --
  354. --    IRND := 0;
  355. --    BETAM1 := BETA - ONE;
  356. --    if ((A + BETAM1) - A) /= ZERO  then
  357. --      IRND := 1;
  358. --    end if;
  359. --
  360. --
  361. --    NEGEP := IT + 3;
  362. --    BETAIN := ONE / BETA;
  363. --    A := ONE;
  364. --  --  for I in 1..NEGEP  loop
  365. --  for I in 1..50  loop
  366. --  exit when I > NEGEP;
  367. --      A := A * BETAIN;
  368. --    end loop;
  369. --    B := A;
  370. --    while ((ONE - A) - ONE) = ZERO  loop
  371. --      A := A * BETA;
  372. --      NEGEP := NEGEP - 1;
  373. --    end loop;
  374. --    NEGEP := -NEGEP;
  375. --
  376. --
  377. --    EPSNEG := A;
  378. --    if (IBETA /= 2) and (IRND /= 0)  then
  379. --      A := (A * (ONE + A)) / (ONE + ONE);
  380. --      if ((ONE - A) - ONE) /= ZERO  then
  381. --        EPSNEG := A;
  382. --      end if;
  383. --    end if;
  384. --
  385. --
  386. --    MACHEP := -IT - 3;
  387. --    A := B;
  388. --    while ((ONE + A) - ONE) = ZERO  loop
  389. --      A := A * BETA;
  390. --      MACHEP := MACHEP + 1;
  391. --    end loop;
  392. --
  393. --
  394. --    EPS := A;
  395. --    if (IBETA /= 2) and (IRND /= 0)  then
  396. --      A := (A * (ONE + A)) / (ONE + ONE);
  397. --      if ((ONE + A) - ONE) /= ZERO  then
  398. --        EPS := A;
  399. --      end if;
  400. --    end if;
  401. --
  402. --
  403. --    NGRD := 0;
  404. --    if ((IRND = 0) and ((ONE + EPS) * ONE - ONE) /= ZERO)  then
  405. --      NGRD := 1;
  406. --    end if;
  407. --
  408. --
  409. --    I := 0;
  410. --    K := 1;
  411. --    Z := BETAIN;
  412. --    loop
  413. --      Y := Z;
  414. --      Z := Y * Y;
  415. --      A := Z * ONE;
  416. --      exit when ((A + A) = ZERO) or (ABS(Z) >= Y);
  417. --      I := I + 1;
  418. --      K := K + K;
  419. --    end loop;
  420. --    if (IBETA /= 10)  then
  421. --      IEXP := I + 1;
  422. --      MX := K + K;
  423. --    else
  424. --      IEXP := 2;
  425. --      IZ := IBETA;
  426. --      while (K >= IZ)  loop
  427. --        IZ := IZ * IBETA;
  428. --        IEXP := IEXP + 1;
  429. --      end loop;
  430. --      MX := IZ + IZ - 1;
  431. --    end if;
  432. --
  433. --    loop
  434. --      XMIN := Y;
  435. --      Y := Y * BETAIN;
  436. --      A := Y * ONE;
  437. --      exit when ((A + A) = ZERO) or (ABS(Y) >= XMIN);
  438. --      K := K + 1;
  439. --    end loop;
  440. --
  441. --
  442. --    MINEXP := -K;
  443. --
  444. --
  445. --    if ((MX <= (K + K - 3)) and (IBETA /= 10))  then
  446. --      MX := MX + MX;
  447. --      IEXP := IEXP + 1;
  448. --    end if;
  449. --
  450. --
  451. --    MAXEXP := MX + MINEXP;
  452. --    I := MAXEXP + MINEXP;
  453. --    if ((IBETA = 2) and (I = 0))  then
  454. --      MAXEXP := MAXEXP - 1;
  455. --    end if;
  456. --    if (I > 20)  then
  457. --      MAXEXP := MAXEXP - 1;
  458. --    end if;
  459. --    if (A /= Y)  then
  460. --      MAXEXP := MAXEXP - 2;
  461. --    end if;
  462. --
  463. --
  464. --    XMAX := ONE - EPSNEG;
  465. --    if ((XMAX * ONE) /= XMAX)  then
  466. --      XMAX := ONE - BETA * EPSNEG;
  467. --    end if;
  468. --    XMAX := XMAX / (BETA * BETA * BETA * XMIN);
  469. --    I := MAXEXP + MINEXP + 3;
  470. --    if I > 0  then
  471. --      for J in 1..50  loop
  472. --  exit when J > I;
  473. --        if IBETA = 2  then
  474. --          XMAX := XMAX + XMAX;
  475. --        else
  476. --          XMAX := XMAX * BETA;
  477. --        end if;
  478. --      end loop;
  479. --    end if;
  480. --
  481. --PUT("INITIALIZED"); NEW_LINE;
  482.  
  483. end FLOATING_CHARACTERISTICS;
  484.  
  485. with FLOATING_CHARACTERISTICS;
  486. use FLOATING_CHARACTERISTICS;
  487. package body NUMERIC_PRIMITIVES is
  488.  
  489.  
  490.   function SIGN(X, Y : FLOAT) return FLOAT is
  491.     --  Returns the value of X with the sign of Y
  492.   begin
  493.     if Y >= 0.0  then
  494.       return X;
  495.     else
  496.       return -X;
  497.     end if;
  498.   end SIGN;
  499.  
  500.   function MAX(X, Y : FLOAT) return FLOAT is
  501.   begin
  502.     if X >= Y  then
  503.       return X;
  504.     else
  505.       return Y;
  506.     end if;
  507.   end MAX;
  508.  
  509.   function TRUNCATE(X : FLOAT) return FLOAT is
  510.   --  Optimum code depends on how the system rounds at exact halves
  511.   begin
  512.     if FLOAT(INTEGER(X)) = X  then
  513.       return X;
  514.     end if;
  515.     if X > ZERO  then
  516.       return FLOAT(INTEGER(X - HALF));
  517.     elsif X = ZERO  then
  518.       return ZERO;
  519.     else
  520.       return FLOAT(INTEGER(X + HALF));
  521.     end if;
  522.   end TRUNCATE;
  523.  
  524.   function ROUND(X : FLOAT) return FLOAT is
  525.   begin
  526.     return FLOAT(INTEGER(X));
  527.   end ROUND;
  528.  
  529.  
  530.   package KEY is
  531.     X : INTEGER := 10_001;
  532.     Y : INTEGER := 20_001;
  533.     Z : INTEGER := 30_001;
  534.   end KEY;
  535.  
  536.   function RAN return FLOAT is
  537.   --  This rectangular random number routine is adapted from a report
  538.   --  "A Pseudo-Random Number Generator" by B. A. Wichmann and I. D. Hill
  539.   --  NPL Report DNACS XX (to be published)
  540.   --  In this stripped version, it is suitable for machines supporting 
  541.   --  INTEGER at only 16 bits and is portable in Ada
  542.     W : FLOAT;
  543.   begin
  544.  
  545.     KEY.X := 171 * (KEY.X mod 177 - 177) -  2 * (KEY.X / 177);
  546.     if KEY.X < 0  then
  547.       KEY.X := KEY.X + 30269;
  548.     end if;
  549.  
  550.     KEY.Y := 172 * (KEY.Y mod 176 - 176) - 35 * (KEY.Y / 176);
  551.     if KEY.Y < 0  then
  552.       KEY.Y := KEY.Y + 30307;
  553.     end if;
  554.  
  555.     KEY.Z := 170 * (KEY.Z mod 178 - 178) - 63 * (KEY.Z / 178);
  556.     if KEY.Z < 0  then
  557.       KEY.Z := KEY.Z + 30323;
  558.     end if;
  559.  
  560.     --  CONVERT_TO_FLOAT is used instead of FLOAT since the floating
  561.     --  type may be software defined
  562.  
  563.     W :=     CONVERT_TO_FLOAT(KEY.X)/30269.0
  564.            + CONVERT_TO_FLOAT(KEY.Y)/30307.0
  565.            + CONVERT_TO_FLOAT(KEY.Z)/30323.0;
  566.  
  567.     return  W - CONVERT_TO_FLOAT(INTEGER(W - 0.5));
  568.  
  569.   end RAN;
  570.  
  571.  
  572. begin
  573.  
  574.   ZERO  := CONVERT_TO_FLOAT(INTEGER(0));
  575.   ONE   := CONVERT_TO_FLOAT(INTEGER(1));
  576.   TWO   := ONE + ONE;
  577.   THREE := ONE + ONE + ONE;
  578.   HALF  := ONE / TWO;
  579.  
  580.   PI            := CONVERT_TO_FLOAT(INTEGER(3)) +
  581.                    CONVERT_TO_FLOAT(MANTISSA_TYPE(0.14159_26535_89793_23846));
  582.   ONE_OVER_PI   := CONVERT_TO_FLOAT(MANTISSA_TYPE(0.31830_98861_83790_67154));
  583.   TWO_OVER_PI   := CONVERT_TO_FLOAT(MANTISSA_TYPE(0.63661_97723_67581_34308));
  584.   PI_OVER_TWO   := CONVERT_TO_FLOAT(INTEGER(1)) +
  585.                    CONVERT_TO_FLOAT(MANTISSA_TYPE(0.57079_63267_94896_61923));
  586.   PI_OVER_THREE := CONVERT_TO_FLOAT(INTEGER(1)) +
  587.                    CONVERT_TO_FLOAT(MANTISSA_TYPE(0.04719_75511_96597_74615));
  588.   PI_OVER_FOUR  := CONVERT_TO_FLOAT(MANTISSA_TYPE(0.78539_81633_97448_30962));
  589.   PI_OVER_SIX   := CONVERT_TO_FLOAT(MANTISSA_TYPE(0.52359_87755_98298_87308));
  590.  
  591. end NUMERIC_PRIMITIVES;
  592.  
  593. with TEXT_IO;
  594. with FLOATING_CHARACTERISTICS;
  595. with NUMERIC_PRIMITIVES;
  596. package body CORE_FUNCTIONS is
  597.   use TEXT_IO;
  598.   use FLOATING_CHARACTERISTICS;
  599.   use NUMERIC_PRIMITIVES;
  600.   package FLT_IO is new FLOAT_IO(FLOAT);
  601.   use FLT_IO;
  602.  
  603. --  The following routines are coded directly from the algorithms and
  604. --  coeficients given in "Software Manual for the Elementry Functions"
  605. --  by William J. Cody, Jr. and William Waite, Prentice_Hall, 1980
  606. --  CBRT by analogy
  607. --  A more general formulation uses MANTISSA_TYPE, etc.
  608. --  The coeficients are appropriate for 25 to 32 bits floating significance
  609. --  They will work for less but slightly shorter versions are possible
  610. --  The routines are coded to stand alone so they need not be compiled together
  611.  
  612. --  These routines have been coded to accept a general MANTISSA_TYPE
  613. --  That is, they are designed to work with a manitssa either fixed of float
  614. --  There are some explicit conversions which are required but these will
  615. --  not cause any extra code to be generated
  616.  
  617. --      16 JULY 1982       W A WHITAKER  AFATL EGLIN AFB FL 32542
  618. --                         T C EICHOLTZ  USAFA
  619.  
  620.  
  621.   function SQRT(X : FLOAT) return FLOAT is
  622.     M, N : EXPONENT_TYPE;
  623.     F, Y : MANTISSA_TYPE;
  624.     RESULT : FLOAT;
  625.  
  626.     subtype INDEX is INTEGER range 0..100;    --  #########################
  627.     SQRT_L1 : INDEX := 3;
  628.     --  Could get away with SQRT_L1 := 2 for 28 bits
  629.     --  Using the better Cody-Waite coeficients overflows MANTISSA_TYPE
  630.     SQRT_C1 : MANTISSA_TYPE := 8#0.3317777777#;
  631.     SQRT_C2 : MANTISSA_TYPE := 8#0.4460000000#;
  632.     SQRT_C3 : MANTISSA_TYPE := 8#0.55202_36314_77747_36311_0#;
  633.  
  634.   begin
  635.     if X = ZERO  then
  636.       RESULT := ZERO;
  637.       return RESULT;
  638.     elsif X = ONE  then            --  To get exact SQRT(1.0)
  639.       RESULT := ONE;
  640.       return RESULT;
  641.     elsif X < ZERO  then
  642.       NEW_LINE;
  643.       PUT("CALLED SQRT FOR NEGATIVE ARGUMENT   ");
  644.       PUT(X);
  645.       PUT("   USED ABSOLUTE VALUE");
  646.       NEW_LINE;
  647.       RESULT := SQRT(ABS(X));
  648.       return RESULT;
  649.     else
  650.       DEFLOAT(X, N, F);
  651.       Y := SQRT_C1 + MANTISSA_TYPE(SQRT_C2 * F);
  652.       for J in 1..SQRT_L1  loop
  653.         Y := Y/MANTISSA_DIVISOR_2 + MANTISSA_TYPE((F/MANTISSA_DIVISOR_2)/Y);
  654.       end loop;
  655.       if (N mod 2) /= 0  then
  656.         Y := MANTISSA_TYPE(SQRT_C3 * Y);
  657.         N := N + 1;
  658.       end if;
  659.       M := N/2;
  660.       REFLOAT(M,Y,RESULT);
  661.       return RESULT;
  662.     end if;
  663.   exception
  664.   when others =>
  665.     NEW_LINE; PUT(" EXCEPTION IN SQRT, X = "); PUT(X);
  666.     PUT("  RETURNED 1.0"); NEW_LINE;
  667.     return ONE;
  668.   end SQRT;
  669.  
  670.  
  671.   function CBRT(X : FLOAT) return FLOAT is
  672.     M, N : EXPONENT_TYPE;
  673.     F, Y : MANTISSA_TYPE;
  674.     RESULT : FLOAT;
  675.  
  676.     subtype INDEX is INTEGER range 0..100;    --  #########################
  677.     CBRT_L1 : INDEX := 3;
  678.     CBRT_C1 : MANTISSA_TYPE := 0.5874009;
  679.     CBRT_C2 : MANTISSA_TYPE := 0.4125990;
  680.     CBRT_C3 : MANTISSA_TYPE := 0.62996_05249;
  681.     CBRT_C4 : MANTISSA_TYPE := 0.79370_05260;
  682.  
  683.   begin
  684.     if X = ZERO then
  685.       RESULT := ZERO;
  686.       return RESULT;
  687.     else
  688.       DEFLOAT(X, N, F);
  689.       F := ABS(F);
  690.       Y := CBRT_C1 + MANTISSA_TYPE(CBRT_C2 * F);
  691.       for J in 1 .. CBRT_L1 loop
  692.         Y :=     Y
  693.             - (  Y/MANTISSA_DIVISOR_3 
  694.                - MANTISSA_TYPE((F/MANTISSA_DIVISOR_3) / MANTISSA_TYPE(Y*Y)) );
  695.       end loop;
  696.       case (N mod 3) is
  697.         when 0 =>
  698.           null;
  699.         when 1 =>
  700.           Y := MANTISSA_TYPE(CBRT_C3 * Y);
  701.           N := N + 2;
  702.         when 2 =>
  703.           Y := MANTISSA_TYPE(CBRT_C4 * Y);
  704.           N := N + 1;
  705.         when others =>
  706.           null;
  707.       end case;
  708.       M := N/3;
  709.       if X < ZERO  then
  710.         Y := -Y;
  711.       end if;
  712.       REFLOAT(M, Y, RESULT);
  713.       return RESULT;
  714.     end if;
  715.   exception
  716.     when others =>
  717.       RESULT := ONE;
  718.       if X < ZERO then
  719.       RESULT := - ONE;
  720.       end if;
  721.       NEW_LINE; PUT("EXCEPTION IN CBRT, X = "); PUT(X);
  722.       PUT("  RETURNED  "); PUT(RESULT); NEW_LINE;
  723.       return RESULT;
  724.   end CBRT;
  725.  
  726.     function LOG(X : FLOAT) return FLOAT is
  727.   --  Uses fixed formulation for generality
  728.  
  729.     RESULT : FLOAT;
  730.     N : EXPONENT_TYPE;
  731.     XN : FLOAT;
  732.     Y : FLOAT;
  733.     F : MANTISSA_TYPE;
  734.     Z, ZDEN, ZNUM : MANTISSA_TYPE;
  735.  
  736.     C0 : constant MANTISSA_TYPE := 0.20710_67811_86547_52440;
  737.                                                --  SQRT(0.5) - 0.5
  738.     C1 : constant FLOAT := 8#0.543#;
  739.     C2 : constant FLOAT :=-2.12194_44005_46905_82767_9E-4;
  740.  
  741.     function R(Z : MANTISSA_TYPE) return MANTISSA_TYPE is
  742.     --  Use fixed formulation here because the float coeficents are > 1.0
  743.     --  and would exceed the limits on a MANTISSA_TYPE
  744.       A0 : constant MANTISSA_TYPE := 0.04862_85276_587;
  745.       B0 : constant MANTISSA_TYPE := 0.69735_92187_803;
  746.       B1 : constant MANTISSA_TYPE :=-0.125;
  747.       C  : constant MANTISSA_TYPE := 0.01360_09546_862;
  748.     begin
  749.       return Z + MANTISSA_TYPE(Z * 
  750.           MANTISSA_TYPE(MANTISSA_TYPE(Z * Z) * (C +
  751.           MANTISSA_TYPE(A0/(B0 + MANTISSA_TYPE(B1 * MANTISSA_TYPE(Z * Z)))))));
  752.     end R;
  753.  
  754.   begin
  755.  
  756.     if X < ZERO      then
  757.       NEW_LINE;
  758.       PUT("CALLED LOG FOR NEGATIVE ");
  759.       PUT(X);
  760.       PUT("   USE ABS => ");
  761.       RESULT := LOG(ABS(X));
  762.       PUT(RESULT);
  763.       NEW_LINE;
  764.     elsif X = ZERO  then
  765.       NEW_LINE;
  766.       PUT("CALLED LOG FOR ZERO ARGUMENT, RETURNED ");
  767.       RESULT := -XMAX;      --  SUPPOSED TO BE -LARGE
  768.       PUT(RESULT);
  769.       NEW_LINE;
  770.     else
  771.       DEFLOAT(X,N,F);
  772.       ZNUM := F - MANTISSA_HALF;
  773.       Y := CONVERT_TO_FLOAT(ZNUM);
  774.       ZDEN := ZNUM / MANTISSA_DIVISOR_2 + MANTISSA_HALF;
  775.       if ZNUM > C0  then
  776.         Y := Y - MANTISSA_HALF;
  777.         ZNUM := ZNUM - MANTISSA_HALF;
  778.         ZDEN := ZDEN + MANTISSA_HALF/MANTISSA_DIVISOR_2;
  779.       else
  780.         N := N -1;
  781.       end if;
  782.       Z    := MANTISSA_TYPE(ZNUM / ZDEN);
  783.       RESULT := CONVERT_TO_FLOAT(R(Z));
  784.       if N /= 0  then
  785.         XN := CONVERT_TO_FLOAT(N);
  786.         RESULT := (XN * C2 + RESULT) + XN * C1;
  787.       end if;
  788.     end if;
  789.     return RESULT;
  790.  
  791.   exception
  792.   when others =>
  793.     NEW_LINE; PUT(" EXCEPTION IN LOG, X = "); PUT(X);
  794.     PUT("  RETURNED 0.0"); NEW_LINE;
  795.     return ZERO;
  796.   end LOG;
  797.  
  798.  
  799.   function LOG10(X : FLOAT) return FLOAT is
  800.     LOG_10_OF_2 : constant FLOAT :=
  801.              CONVERT_TO_FLOAT(MANTISSA_TYPE(8#0.33626_75425_11562_41615#));
  802.   begin
  803.     return LOG(X) * LOG_10_OF_2;
  804.   end LOG10;
  805.  
  806.   function EXP(X : FLOAT) return FLOAT is
  807.  
  808.     RESULT : FLOAT;
  809.     N : EXPONENT_TYPE;
  810.     XG, XN, X1, X2 : FLOAT;
  811.     F, G : MANTISSA_TYPE;
  812.  
  813.     BIGX : FLOAT := EXP_LARGE;
  814.     SMALLX : FLOAT := EXP_SMALL;
  815.  
  816.     ONE_OVER_LOG_2 : constant FLOAT :=  1.4426_95040_88896_34074;
  817.     C1 : constant FLOAT :=  0.69335_9375;
  818.     C2 : constant FLOAT := -2.1219_44400_54690_58277E-4;
  819.  
  820.     function R(G : MANTISSA_TYPE) return MANTISSA_TYPE is
  821.       Z , GP, Q : MANTISSA_TYPE;
  822.  
  823.       P0 : constant MANTISSA_TYPE :=  0.24999_99999_9992;
  824.       P1 : constant MANTISSA_TYPE :=  0.00595_04254_9776;
  825.       Q0 : constant MANTISSA_TYPE :=  0.5;
  826.       Q1 : constant MANTISSA_TYPE :=  0.05356_75176_4522;
  827.       Q2 : constant MANTISSA_TYPE :=  0.00029_72936_3682;
  828.     begin
  829.       Z  := MANTISSA_TYPE(G * G);
  830.       GP := MANTISSA_TYPE( (MANTISSA_TYPE(P1 * Z) + P0) * G );
  831.       Q  := MANTISSA_TYPE( (MANTISSA_TYPE(Q2 * Z) + Q1) * Z ) + Q0;
  832.       return MANTISSA_HALF + MANTISSA_TYPE( GP /(Q - GP) );
  833.     end R;
  834.  
  835.  
  836.   begin
  837.  
  838.     if X > BIGX  then
  839.       NEW_LINE;
  840.       PUT("  EXP CALLED WITH TOO BIG A POSITIVE ARGUMENT, ");
  841.           PUT(X); PUT("   RETURNED XMAX");
  842.       NEW_LINE;
  843.       RESULT := XMAX;
  844.     elsif X < SMALLX  then
  845.       NEW_LINE;
  846.       PUT("  EXP CALLED WITH TOO BIG A NEGATIVE ARGUMENT,  ");
  847.           PUT(X); PUT("    RETURNED ZERO");
  848.       NEW_LINE;
  849.       RESULT := ZERO;
  850.     elsif ABS(X) < EPS  then
  851.       RESULT := ONE;
  852.     else
  853.       N  := EXPONENT_TYPE(X * ONE_OVER_LOG_2);
  854.       XN := CONVERT_TO_FLOAT(N);
  855.       X1 := ROUND(X);
  856.       X2 := X - X1;
  857.       XG := ( (X1 - XN * C1) + X2 ) - XN * C2;
  858.       G  := MANTISSA_TYPE(XG);
  859.       N  := N + 1;
  860.       F := R(G);
  861.       REFLOAT(N, F, RESULT);
  862.     end if;
  863.     return RESULT;
  864.  
  865.   exception
  866.   when others =>
  867.     NEW_LINE; PUT(" EXCEPTION IN EXP, X = "); PUT(X);
  868.     PUT("  RETURNED 1.0"); NEW_LINE;
  869.     return ONE;
  870.   end EXP;
  871.  
  872. function "**" (X, Y : FLOAT) return FLOAT is
  873. --  This is the last function to be coded since it appeared that it really
  874. --  was un-Ada-like and ought not be in the regular package
  875. --  Nevertheless it was included in this version
  876. --  It is specific for FLOAT and does not have the MANTISSA_TYPE generality
  877.   M, N : EXPONENT_TYPE;
  878.   G : MANTISSA_TYPE;
  879.   P, TEMP, IW1, I : INTEGER;
  880.   RESULT, Z, V, R, U1, U2, W, W1, W2, W3, Y1, Y2 : FLOAT;
  881.  
  882.   K : constant FLOAT := 0.44269_50408_88963_40736;
  883.   IBIGX : constant INTEGER := INTEGER(TRUNCATE(16.0 * LOG(XMAX) - 1.0));
  884.   ISMALLX : constant INTEGER := INTEGER(TRUNCATE(16.0 * LOG(XMIN) + 1.0));
  885.  
  886.   P1 : constant FLOAT := 0.83333_32862_45E-1;
  887.   P2 : constant FLOAT := 0.12506_48500_52E-1;
  888.  
  889.   Q1 : constant FLOAT := 0.69314_71805_56341;
  890.   Q2 : constant FLOAT := 0.24022_65061_44710;
  891.   Q3 : constant FLOAT := 0.55504_04881_30765E-1;
  892.   Q4 : constant FLOAT := 0.96162_06595_83789E-2;
  893.   Q5 : constant FLOAT := 0.13052_55159_42810E-2;
  894.  
  895.   A1 : array (1 .. 17) of FLOAT:=
  896.      (  8#1.00000_0000#,        
  897.         8#0.75222_5750#,        
  898.         8#0.72540_3067#,        
  899.         8#0.70146_3367#,        
  900.         8#0.65642_3746#,        
  901.         8#0.63422_2140#,        
  902.         8#0.61263_4520#,        
  903.         8#0.57204_2434#,        
  904.         8#0.55202_3631#,        
  905.         8#0.53254_0767#,        
  906.         8#0.51377_3265#,        
  907.         8#0.47572_4623#,        
  908.         8#0.46033_7602#,        
  909.         8#0.44341_7233#,        
  910.         8#0.42712_7017#,        
  911.         8#0.41325_3033#,        
  912.         8#0.40000_0000#  );        
  913.                 
  914.   A2 : array (1 .. 8) of FLOAT :=
  915.      (  8#0.00000_00005_22220_66302_61734_72062#,
  916.         8#0.00000_00003_02522_47021_04062_61124#,
  917.         8#0.00000_00005_21760_44016_17421_53016#,
  918.         8#0.00000_00007_65401_41553_72504_02177#,
  919.         8#0.00000_00002_44124_12254_31114_01243#,
  920.         8#0.00000_00000_11064_10432_66404_42174#,
  921.         8#0.00000_00004_72542_16063_30176_55544#,
  922.         8#0.00000_00001_74611_03661_23056_22556#  );
  923.        
  924.  
  925.   function REDUCE (V : FLOAT) return FLOAT is
  926.   begin
  927.     return FLOAT(INTEGER(16.0 * V)) * 0.0625;
  928.   end REDUCE;
  929.  
  930.   begin
  931.     if X <= ZERO then
  932.       if X < ZERO then
  933.         RESULT := (ABS(X))**Y;
  934.         NEW_LINE;
  935.         PUT("X**Y CALLED WITH X = "); PUT(X); NEW_LINE;
  936.         PUT("USED ABS, RETURNED "); PUT(RESULT); NEW_LINE;
  937.       else
  938.         if Y <= ZERO then
  939.           if Y = ZERO then
  940.             RESULT := ZERO;
  941.           else
  942.             RESULT := XMAX;
  943.           end if;
  944.           NEW_LINE;
  945.           PUT("X**Y CALLED WITH X = 0, Y = "); PUT(Y); NEW_LINE;
  946.           PUT("RETURNED "); PUT(RESULT); NEW_LINE;
  947.         else
  948.           RESULT := ZERO;
  949.         end if;
  950.       end if;
  951.     else
  952.       DEFLOAT(X, M, G);
  953.       P := 1;
  954.       if G <= A1(9) then
  955.         P := 9;
  956.       end if;
  957.       if G <= A1(P+4) then
  958.         P := P + 4;
  959.       end if;
  960.       if G <= A1(P+2) then
  961.         P := P + 2;
  962.       end if;
  963.       Z := ((G - A1(P+1)) - A2((P+1)/2))/(G + A1(P+1));
  964.       Z := Z + Z;
  965.       V := Z * Z;
  966.       R := (P2 * V + P1) * V * Z;
  967.       R := R + K * R;
  968.       U2 := (R + Z * K) + Z;
  969.       U1 := FLOAT(INTEGER(M) * 16 - P) * 0.0625;
  970.       Y1 := REDUCE(Y);
  971.       Y2 := Y - Y1;
  972.       W := U2 * Y + U1 * Y2;
  973.       W1 := REDUCE(W);
  974.       W2 := W - W1;
  975.       W := W1 + U1 * Y1;
  976.       W1 := REDUCE(W);
  977.       W2 := W2 + (W - W1);
  978.       W3 := REDUCE(W2);
  979.       IW1 := INTEGER(TRUNCATE(16.0 * (W1 + W3)));
  980.       W2 := W2 - W3;
  981.       if W > FLOAT(IBIGX) then
  982.         RESULT := XMAX;
  983.         PUT("X**Y CALLED  X ="); PUT(X); PUT("   Y ="); PUT(Y);
  984.         PUT("   TOO LARGE  RETURNED "); PUT(RESULT); NEW_LINE;
  985.       elsif W < FLOAT(ISMALLX) then
  986.         RESULT := ZERO;
  987.         PUT("X**Y CALLED  X ="); PUT(X); PUT("   Y ="); PUT(Y);
  988.         PUT("   TOO SMALL  RETURNED "); PUT(RESULT); NEW_LINE;
  989.       else
  990.         if W2 > ZERO then
  991.           W2 := W2 - 0.0625;
  992.           IW1 := IW1 + 1;
  993.         end if;
  994.         if IW1 < INTEGER(ZERO) then
  995.           I := 0;
  996.         else 
  997.           I := 1;
  998.         end if;
  999.         M := EXPONENT_TYPE(I + IW1/16);
  1000.         P := 16 * INTEGER(M) - IW1;
  1001.         Z := ((((Q5 * W2 + Q4) * W2 + Q3) * W2 + Q2) * W2 + Q1) * W2;
  1002.         Z := A1(P+1) + (A1(P+1) * Z);  
  1003.  
  1004.         REFLOAT(M, Z, RESULT);
  1005.       end if;
  1006.     end if;
  1007.     return RESULT;
  1008.   end "**";
  1009.  
  1010. begin
  1011.   EXP_LARGE := LOG(XMAX) * (ONE - EPS);
  1012.   EXP_SMALL := LOG(XMIN) * (ONE - EPS);
  1013. end CORE_FUNCTIONS;
  1014. package TRIG_FUNCTIONS is
  1015.   function SIN(X : FLOAT) return FLOAT;
  1016.   function COS(X : FLOAT) return FLOAT;
  1017.   function TAN(X : FLOAT) return FLOAT;
  1018.   function COT(X : FLOAT) return FLOAT;
  1019.   function ASIN(X : FLOAT) return FLOAT;
  1020.   function ACOS(X : FLOAT) return FLOAT;
  1021.   function ATAN(X : FLOAT) return FLOAT;
  1022.   function ATAN2(V, U : FLOAT) return FLOAT;
  1023.   function SINH(X : FLOAT) return FLOAT;
  1024.   function COSH(X : FLOAT) return FLOAT;
  1025.   function TANH(X : FLOAT) return FLOAT;
  1026. end TRIG_FUNCTIONS;
  1027. with TEXT_IO;
  1028. with FLOATING_CHARACTERISTICS;
  1029. with NUMERIC_PRIMITIVES;
  1030. with CORE_FUNCTIONS;
  1031. package body TRIG_FUNCTIONS is
  1032.   use TEXT_IO;
  1033.   use FLOATING_CHARACTERISTICS;
  1034.   use NUMERIC_PRIMITIVES;
  1035.   use CORE_FUNCTIONS;
  1036.   package FLT_IO is new FLOAT_IO(FLOAT);
  1037.   use FLT_IO;
  1038.  
  1039. --  PRELIMINARY VERSION *********************************
  1040.  
  1041. --  The following routines are coded directly from the algorithms and
  1042. --  coeficients given in "Software Manual for the Elementry Functions"
  1043. --  by William J. Cody, Jr. and William Waite, Prentice_Hall, 1980
  1044. --  This particular version is stripped to work with FLOAT and INTEGER
  1045. --  and uses a mantissa represented as a FLOAT
  1046. --  A more general formulation uses MANTISSA_TYPE, etc.
  1047. --  The coeficients are appropriate for 25 to 32 bits floating significance
  1048. --  They will work for less but slightly shorter versions are possible
  1049. --  The routines are coded to stand alone so they need not be compiled together
  1050.  
  1051. --      16 JULY 1982       W A WHITAKER  AFATL EGLIN AFB FL 32542
  1052. --                         T C EICHOLTZ  USAFA
  1053.  
  1054.  
  1055.   function SIN(X : FLOAT) return FLOAT is
  1056.     SGN, Y : FLOAT;
  1057.     N : INTEGER;
  1058.     XN : FLOAT;
  1059.     F, G, X1, X2 : FLOAT;
  1060.     RESULT : FLOAT;
  1061.  
  1062.     YMAX : FLOAT := FLOAT(INTEGER(PI * TWO**(IT/2)));
  1063.     BETA : FLOAT := CONVERT_TO_FLOAT(IBETA);
  1064.     EPSILON : FLOAT := BETA ** (-IT/2);
  1065.  
  1066.     C1 : constant FLOAT :=  3.140625;
  1067.     C2 : constant FLOAT :=  9.6765_35897_93E-4;
  1068.  
  1069.     function R(G : FLOAT) return FLOAT is
  1070.       R1 : constant FLOAT := -0.16666_66660_883;
  1071.       R2 : constant FLOAT :=  0.83333_30720_556E-2;
  1072.       R3 : constant FLOAT := -0.19840_83282_313E-3;
  1073.       R4 : constant FLOAT :=  0.27523_97106_775E-5;
  1074.       R5 : constant FLOAT := -0.23868_34640_601E-7;
  1075.     begin
  1076.       return ((((R5*G + R4)*G + R3)*G + R2)*G + R1)*G;
  1077.     end R;
  1078.  
  1079.   begin
  1080.     if X < ZERO  then
  1081.       SGN := -ONE;
  1082.       Y := -X;
  1083.     else
  1084.       SGN := ONE;
  1085.       Y := X;
  1086.     end if;
  1087.  
  1088.     if Y > YMAX  then
  1089.       NEW_LINE;
  1090.       PUT(" SIN CALLED WITH ARGUMENT TOO LARGE FOR ACCURACY ");
  1091.       PUT(X); NEW_LINE;
  1092.     end if;
  1093.  
  1094.     N := INTEGER(Y * ONE_OVER_PI);
  1095.     XN := CONVERT_TO_FLOAT(N);
  1096.     if N mod 2 /= 0  then
  1097.       SGN := -SGN;
  1098.     end if;
  1099.     X1 := TRUNCATE(ABS(X));
  1100.     X2 := ABS(X) - X1;
  1101.     F := ((X1 - XN*C1) + X2) - XN*C2;
  1102.     if ABS(F) < EPSILON  then
  1103.       RESULT := F;
  1104.     else
  1105.       G := F * F;
  1106.       RESULT := F + F*R(G);
  1107.     end if;
  1108.     return (SGN * RESULT);
  1109.   end SIN;
  1110.  
  1111.  
  1112.   function COS(X : FLOAT) return FLOAT is
  1113.     SGN, Y : FLOAT;
  1114.     N : INTEGER;
  1115.     XN : FLOAT;
  1116.     F, G, X1, X2 : FLOAT;
  1117.     RESULT : FLOAT;
  1118.  
  1119.     YMAX : FLOAT := FLOAT(INTEGER(PI * TWO**(IT/2)));
  1120.     BETA : FLOAT := CONVERT_TO_FLOAT(IBETA);
  1121.     EPSILON : FLOAT := BETA ** (-IT/2);
  1122.  
  1123.     C1 : constant FLOAT :=  3.140625;
  1124.     C2 : constant FLOAT :=  9.6765_35897_93E-4;
  1125.  
  1126.     function R(G : FLOAT) return FLOAT is
  1127.       R1 : constant FLOAT := -0.16666_66660_883;
  1128.       R2 : constant FLOAT :=  0.83333_30720_556E-2;
  1129.       R3 : constant FLOAT := -0.19840_83282_313E-3;
  1130.       R4 : constant FLOAT :=  0.27523_97106_775E-5;
  1131.       R5 : constant FLOAT := -0.23868_34640_601E-7;
  1132.     begin
  1133.       return ((((R5*G + R4)*G + R3)*G + R2)*G + R1)*G;
  1134.     end R;
  1135.  
  1136.   begin
  1137.     SGN := 1.0;
  1138.     Y := ABS(X) + PI_OVER_TWO;
  1139.  
  1140.     if Y > YMAX  then
  1141.       NEW_LINE;
  1142.       PUT(" COS CALLED WITH ARGUMENT TOO LARGE FOR ACCURACY ");
  1143.       PUT(X); NEW_LINE;
  1144.     end if;
  1145.  
  1146.     N := INTEGER(Y * ONE_OVER_PI);
  1147.     XN := CONVERT_TO_FLOAT(N);
  1148.     if N mod 2 /= 0  then
  1149.       SGN := -SGN;
  1150.     end if;
  1151.     XN := XN - 0.5;          -- TO FORM COS INSTEAD OF SIN
  1152.     X1 := TRUNCATE(ABS(X));
  1153.     X2 := ABS(X) - X1;
  1154.     F := ((X1 - XN*C1) + X2) - XN*C2;
  1155.     if ABS(F) < EPSILON  then
  1156.       RESULT := F;
  1157.     else
  1158.       G := F * F;
  1159.       RESULT := F + F*R(G);
  1160.     end if;
  1161.     return (SGN * RESULT);
  1162.   end COS;
  1163.  
  1164.  
  1165.   function TAN(X : FLOAT) return FLOAT is
  1166.     SGN, Y : FLOAT;
  1167.     N : INTEGER;
  1168.     XN : FLOAT;
  1169.     F, G, X1, X2 : FLOAT;
  1170.     RESULT : FLOAT;
  1171.  
  1172.     YMAX : FLOAT := FLOAT(INTEGER(PI * TWO**(IT/2))) /2.0;
  1173.     BETA : FLOAT := CONVERT_TO_FLOAT(IBETA);
  1174.     EPSILON : FLOAT := BETA ** (-IT/2);
  1175.  
  1176.     C1 : constant FLOAT :=  8#1.444#;
  1177.     C2 : constant FLOAT :=  4.8382_67948_97E-4;
  1178.  
  1179.     function R(G : FLOAT) return FLOAT is
  1180.       P0 : constant FLOAT :=  1.0;
  1181.       P1 : constant FLOAT := -0.11136_14403_566;
  1182.       P2 : constant FLOAT :=  0.10751_54738_488E-2;
  1183.       Q0 : constant FLOAT :=  1.0;
  1184.       Q1 : constant FLOAT := -0.44469_47720_281;
  1185.       Q2 : constant FLOAT :=  0.15973_39213_300E-1;
  1186.     begin
  1187.       return ((P2*G + P1)*G*F + F) / (((Q2*G + Q1)*G +0.5) + 0.5);
  1188.     end R;
  1189.  
  1190.   begin
  1191.     Y := ABS(X);
  1192.     if Y > YMAX  then
  1193.       NEW_LINE;
  1194.       PUT(" TAN CALLED WITH ARGUMENT TOO LARGE FOR ACCURACY ");
  1195.       PUT(X); NEW_LINE;
  1196.     end if;
  1197.  
  1198.     N := INTEGER(X * TWO_OVER_PI);
  1199.     XN := CONVERT_TO_FLOAT(N);
  1200.     X1 := TRUNCATE(X);
  1201.     X2 := X - X1;
  1202.     F := ((X1 - XN*C1) + X2) - XN*C2;
  1203.     if ABS(F) < EPSILON  then
  1204.       RESULT := F;
  1205.     else
  1206.       G := F * F;
  1207.       RESULT := R(G);
  1208.     end if;
  1209.     if N mod 2 = 0  then
  1210.       return RESULT;
  1211.     else
  1212.       return -1.0/RESULT;
  1213.     end if;
  1214.   end TAN;
  1215.  
  1216.   function COT(X : FLOAT) return FLOAT is
  1217.     SGN, Y : FLOAT;
  1218.     N : INTEGER;
  1219.     XN : FLOAT;
  1220.     F, G, X1, X2 : FLOAT;
  1221.     RESULT : FLOAT;
  1222.  
  1223.  
  1224.     YMAX : FLOAT := FLOAT(INTEGER(PI * TWO**(IT/2))) /2.0;
  1225.     BETA : FLOAT := CONVERT_TO_FLOAT(IBETA);
  1226.     EPSILON : FLOAT := BETA ** (-IT/2);
  1227.     EPSILON1 : FLOAT :=  1.0/XMAX;
  1228.  
  1229.     C1 : constant FLOAT :=  8#1.444#;
  1230.     C2 : constant FLOAT :=  4.8382_67948_97E-4;
  1231.  
  1232.     function R(G : FLOAT) return FLOAT is
  1233.       P0 : constant FLOAT :=  1.0;
  1234.       P1 : constant FLOAT := -0.11136_14403_566;
  1235.       P2 : constant FLOAT :=  0.10751_54738_488E-2;
  1236.       Q0 : constant FLOAT :=  1.0;
  1237.       Q1 : constant FLOAT := -0.44469_47720_281;
  1238.       Q2 : constant FLOAT :=  0.15973_39213_300E-1;
  1239.     begin
  1240.       return ((P2*G + P1)*G*F + F) / (((Q2*G + Q1)*G +0.5) + 0.5);
  1241.     end R;
  1242.  
  1243.   begin
  1244.     Y := ABS(X);
  1245.     if Y < EPSILON1  then
  1246.       NEW_LINE;
  1247.       PUT(" COT CALLED WITH ARGUMENT TOO NEAR ZERO ");
  1248.       PUT(X); NEW_LINE;
  1249.       if X < 0.0  then
  1250.         return -XMAX;
  1251.       else
  1252.         return XMAX;
  1253.       end if;
  1254.     end if;
  1255.     if Y > YMAX  then
  1256.       NEW_LINE;
  1257.       PUT(" COT CALLED WITH ARGUMENT TOO LARGE FOR ACCURACY ");
  1258.       PUT(X); NEW_LINE;
  1259.     end if;
  1260.  
  1261.     N := INTEGER(X * TWO_OVER_PI);
  1262.     XN := CONVERT_TO_FLOAT(N);
  1263.     X1 := TRUNCATE(X);
  1264.     X2 := X - X1;
  1265.     F := ((X1 - XN*C1) + X2) - XN*C2;
  1266.     if ABS(F) < EPSILON  then
  1267.       RESULT := F;
  1268.     else
  1269.       G := F * F;
  1270.       RESULT := R(G);
  1271.     end if;
  1272.     if N mod 2 /= 0  then
  1273.       return -RESULT;
  1274.     else
  1275.       return 1.0/RESULT;
  1276.     end if;
  1277.   end COT;
  1278.  
  1279.  
  1280.   function ASIN(X : FLOAT) return FLOAT is
  1281.     G, Y : FLOAT;
  1282.     RESULT : FLOAT;
  1283.     BETA : FLOAT := CONVERT_TO_FLOAT(IBETA);
  1284.     EPSILON : FLOAT := BETA ** (-IT/2);
  1285.  
  1286.     function R(G : FLOAT) return FLOAT is
  1287.     P1 : constant FLOAT := -0.27516_55529_0596E1;
  1288.     P2 : constant FLOAT :=  0.29058_76237_4859E1;
  1289.     P3 : constant FLOAT := -0.59450_14419_3246;
  1290.     Q0 : constant FLOAT := -0.16509_93320_2424E2;
  1291.     Q1 : constant FLOAT :=  0.24864_72896_9164E2;
  1292.     Q2 : constant FLOAT := -0.10333_86707_2113E2;
  1293.     Q3 : constant FLOAT :=  1.0;
  1294.     begin
  1295.       return (((P3*G + P2)*G + P1)*G) / (((G + Q2)*G + Q1)*G + Q0);
  1296.     end R;
  1297.  
  1298.   begin
  1299.     Y := ABS(X);
  1300.  
  1301.     if Y > HALF  then
  1302.       if Y > 1.0  then
  1303.         NEW_LINE; PUT(" ASIN CALLED FOR "); PUT(X);
  1304.             PUT(" (> 1)  TRUNCATED TO 1, CONTINUED"); NEW_LINE;
  1305.         Y := 1.0;
  1306.       end if;
  1307.       G := ((0.5 - Y) + 0.5) / 2.0;
  1308.       Y := -2.0 * SQRT(G);
  1309.       RESULT := Y + Y * R(G);
  1310.       RESULT := (PI_OVER_FOUR + RESULT) + PI_OVER_FOUR;
  1311.     else
  1312.       if Y < EPSILON  then
  1313.         RESULT := Y;
  1314.       else
  1315.         G := Y * Y;
  1316.         RESULT := Y + Y * R(G);
  1317.       end if;
  1318.     end if;
  1319.     if X < 0.0  then
  1320.       RESULT := -RESULT;
  1321.     end if;
  1322.  
  1323.     return RESULT;
  1324.   end ASIN;
  1325.  
  1326.   function ACOS(X : FLOAT) return FLOAT is
  1327.     G, Y : FLOAT;
  1328.     RESULT : FLOAT;
  1329.     BETA : FLOAT := CONVERT_TO_FLOAT(IBETA);
  1330.     EPSILON : FLOAT := BETA ** (-IT/2);
  1331.  
  1332.     function R(G : FLOAT) return FLOAT is
  1333.     P1 : constant FLOAT := -0.27516_55529_0596E1;
  1334.     P2 : constant FLOAT :=  0.29058_76237_4859E1;
  1335.     P3 : constant FLOAT := -0.59450_14419_3246;
  1336.     Q0 : constant FLOAT := -0.16509_93320_2424E2;
  1337.     Q1 : constant FLOAT :=  0.24864_72896_9164E2;
  1338.     Q2 : constant FLOAT := -0.10333_86707_2113E2;
  1339.     Q3 : constant FLOAT :=  1.0;
  1340.     begin
  1341.       return (((P3*G + P2)*G + P1)*G) / (((G + Q2)*G + Q1)*G + Q0);
  1342.     end R;
  1343.  
  1344.   begin
  1345.     Y := ABS(X);
  1346.  
  1347.     if Y > HALF  then
  1348.       if Y > 1.0  then
  1349.         NEW_LINE; PUT(" ACOS CALLED FOR "); PUT(X);
  1350.             PUT(" (> 1)  TRUNCATED TO 1, CONTINUED"); NEW_LINE;
  1351.         Y := 1.0;
  1352.       end if;
  1353.       G := ((0.5 - Y) + 0.5) / 2.0;
  1354.       Y := -2.0 * SQRT(G);
  1355.       RESULT := Y + Y * R(G);
  1356.       if X < 0.0  then
  1357.         RESULT := (PI_OVER_TWO + RESULT) + PI_OVER_TWO;
  1358.       else
  1359.         RESULT := -RESULT;
  1360.       end if;
  1361.  
  1362.     else
  1363.       if Y < EPSILON  then
  1364.         RESULT := Y;
  1365.       else
  1366.         G := Y * Y;
  1367.         RESULT := Y + Y * R(G);
  1368.       end if;
  1369.       if X < 0.0  then
  1370.         RESULT := (PI_OVER_FOUR + RESULT) + PI_OVER_FOUR;
  1371.       else
  1372.         RESULT := (PI_OVER_FOUR - RESULT) + PI_OVER_FOUR;
  1373.       end if;
  1374.     end if;
  1375.  
  1376.     return RESULT;
  1377.   end ACOS;
  1378.  
  1379.  
  1380.   function ATAN(X : FLOAT) return FLOAT is
  1381.     F, G : FLOAT;
  1382.     subtype REGION is INTEGER range 0..3;    --  ##########
  1383.     N : REGION;
  1384.     RESULT : FLOAT;
  1385.  
  1386.     BETA : FLOAT := CONVERT_TO_FLOAT(IBETA);
  1387.  
  1388.     EPSILON : FLOAT := BETA ** (-IT/2);
  1389.  
  1390.     SQRT_3           : constant FLOAT :=  1.73205_08075_68877_29353;
  1391.     SQRT_3_MINUS_1   : constant FLOAT :=  0.73205_08075_68877_29353;
  1392.     TWO_MINUS_SQRT_3 : constant FLOAT :=  0.26794_91924_31122_70647;
  1393.  
  1394.     function R(G : FLOAT) return FLOAT is
  1395.       P0 : constant FLOAT := -0.14400_83448_74E1;
  1396.       P1 : constant FLOAT := -0.72002_68488_98;
  1397.       Q0 : constant FLOAT :=  0.43202_50389_19E1;
  1398.       Q1 : constant FLOAT :=  0.47522_25845_99E1;
  1399.       Q2 : constant FLOAT :=  1.0;
  1400.     begin
  1401.       return ((P1*G + P0)*G) / ((G + Q1)*G + Q0);
  1402.     end R;
  1403.  
  1404.   begin
  1405.     F := ABS(X);
  1406.  
  1407.     if F > 1.0  then
  1408.       F := 1.0 / F;
  1409.       N := 2;
  1410.     else
  1411.       N := 0;
  1412.     end if;
  1413.  
  1414.     if F > TWO_MINUS_SQRT_3  then
  1415.       F := (((SQRT_3_MINUS_1 * F - 0.5) - 0.5) + F) / (SQRT_3 + F);
  1416.       N := N + 1;
  1417.     end if;
  1418.  
  1419.     if ABS(F) < EPSILON  then
  1420.       RESULT := F;
  1421.     else
  1422.       G := F * F;
  1423.       RESULT := F + F * R(G);
  1424.     end if;
  1425.  
  1426.     if N > 1  then
  1427.       RESULT := - RESULT;
  1428.     end if;
  1429.  
  1430.     case N is
  1431.     when 0  =>
  1432.       RESULT := RESULT;
  1433.     when 1  =>
  1434.       RESULT := PI_OVER_SIX + RESULT;
  1435.     when 2  =>
  1436.       RESULT := PI_OVER_TWO + RESULT;
  1437.     when 3  =>
  1438.       RESULT := PI_OVER_THREE + RESULT;
  1439.     end case;
  1440.  
  1441.     if X < 0.0  then
  1442.       RESULT := - RESULT;
  1443.     end if;
  1444.  
  1445.     return RESULT;
  1446.  
  1447.   end ATAN;
  1448.  
  1449.  
  1450.  
  1451.   function ATAN2(V, U : FLOAT) return FLOAT is
  1452.     X, RESULT : FLOAT;
  1453.  
  1454.   begin
  1455.  
  1456.     if U = 0.0  then
  1457.       if V = 0.0  then
  1458.         RESULT := 0.0;
  1459.         NEW_LINE;
  1460.         PUT(" ATAN2 CALLED WITH 0/0   RETURNED "); PUT(RESULT);
  1461.         NEW_LINE;
  1462.       elsif V > 0.0  then
  1463.         RESULT := PI_OVER_TWO;
  1464.       else
  1465.         RESULT := - PI_OVER_TWO;
  1466.       end if;
  1467.  
  1468.     else
  1469.       X := ABS(V/U);
  1470.       --  If underflow or overflow is detected, go to the exception
  1471.       RESULT := ATAN(X);
  1472.       if U < 0.0  then
  1473.         RESULT := PI - RESULT;
  1474.       end if;
  1475.       if V < 0.0  then
  1476.         RESULT := - RESULT;
  1477.       end if;
  1478.     end if;
  1479.     return RESULT;
  1480.   exception
  1481.   when NUMERIC_ERROR  =>
  1482.     if ABS(V) > ABS(U)  then
  1483.       RESULT := PI_OVER_TWO;
  1484.       if V < 0.0  then
  1485.         RESULT := - RESULT;
  1486.       end if;
  1487.     else
  1488.       RESULT := 0.0;
  1489.       if U < 0.0  then
  1490.         RESULT := PI - RESULT;
  1491.       end if;
  1492.     end if;
  1493.     return RESULT;
  1494.   end ATAN2;
  1495.  
  1496.  
  1497.   function SINH(X : FLOAT) return FLOAT is
  1498.     G, W, Y, Z : FLOAT;
  1499.     RESULT : FLOAT;
  1500.     BETA : FLOAT := CONVERT_TO_FLOAT(IBETA);
  1501.     EPSILON : FLOAT := BETA ** (-IT/2);
  1502.  
  1503.     YBAR : FLOAT := EXP_LARGE;
  1504.     LN_V : FLOAT := 8#0.542714#;
  1505.     V_OVER_2_MINUS_1 : FLOAT :=  0.13830_27787_96019_02638E-4;
  1506.     WMAX : FLOAT := YBAR - LN_V + 0.69;
  1507.  
  1508.     function R(G : FLOAT) return FLOAT is
  1509.     P0 : constant FLOAT :=  0.10622_28883_7151E4;
  1510.     P1 : constant FLOAT :=  0.31359_75645_6058E2;
  1511.     P2 : constant FLOAT :=  0.34364_14035_8506;
  1512.     Q0 : constant FLOAT :=  0.63733_73302_1822E4;
  1513.     Q1 : constant FLOAT := -0.13051_01250_9199E3;
  1514.     Q2 : constant FLOAT :=  1.0;
  1515.     begin
  1516.       return (((P2*G + P1)*G + P0)*G) / ((G + Q1)*G + Q0);
  1517.     end R;
  1518.  
  1519.   begin
  1520.     Y := ABS(X);
  1521.  
  1522.     if Y <= 1.0  then
  1523.       if Y < EPSILON  then
  1524.         RESULT := X;
  1525.       else
  1526.         G := X * X;
  1527.         RESULT := X + X * R(G);
  1528.       end if;
  1529.  
  1530.     else
  1531.       if Y <= YBAR  then
  1532.         Z := EXP(Y);
  1533.         RESULT := (Z - 1.0/Z) / 2.0;
  1534.       else
  1535.         W := Y - LN_V;
  1536.         if W > WMAX  then
  1537.           NEW_LINE;
  1538.           PUT(" SINH CALLED WITH TOO LARGE ARGUMENT  "); PUT(X);
  1539.           PUT(" RETURN BIG"); NEW_LINE;
  1540.           W := WMAX;
  1541.         end if;
  1542.         Z := EXP(W);
  1543.         RESULT := Z + V_OVER_2_MINUS_1 * Z;
  1544.       end if;
  1545.       if X < 0.0  then
  1546.         RESULT := -RESULT;
  1547.       end if;
  1548.  
  1549.     end if;
  1550.     return RESULT;
  1551.   end SINH;
  1552.  
  1553.  
  1554.   function COSH(X : FLOAT) return FLOAT is
  1555.     G, W, Y, Z : FLOAT;
  1556.     RESULT : FLOAT;
  1557.     BETA : FLOAT := CONVERT_TO_FLOAT(IBETA);
  1558.     EPSILON : FLOAT := BETA ** (-IT/2);
  1559.  
  1560.     YBAR : FLOAT := EXP_LARGE;
  1561.     LN_V : FLOAT := 8#0.542714#;
  1562.     V_OVER_2_MINUS_1 : FLOAT :=  0.13830_27787_96019_02638E-4;
  1563.     WMAX : FLOAT := YBAR - LN_V + 0.69;
  1564.  
  1565.     function R(G : FLOAT) return FLOAT is
  1566.     P0 : constant FLOAT :=  0.10622_28883_7151E4;
  1567.     P1 : constant FLOAT :=  0.31359_75645_6058E2;
  1568.     P2 : constant FLOAT :=  0.34364_14035_8506;
  1569.     Q0 : constant FLOAT :=  0.63733_73302_1822E4;
  1570.     Q1 : constant FLOAT := -0.13051_01250_9199E3;
  1571.     Q2 : constant FLOAT :=  1.0;
  1572.     begin
  1573.       return (((P2*G + P1)*G + P0)*G) / ((G + Q1)*G + Q0);
  1574.     end R;
  1575.  
  1576.   begin
  1577.     Y := ABS(X);
  1578.  
  1579.     if Y <= YBAR  then
  1580.       Z := EXP(Y);
  1581.       RESULT := (Z + 1.0/Z) / 2.0;
  1582.     else
  1583.       W := Y - LN_V;
  1584.       if W > WMAX  then
  1585.         NEW_LINE;
  1586.         PUT(" COSH CALLED WITH TOO LARGE ARGUMENT  "); PUT(X);
  1587.         PUT(" RETURN BIG"); NEW_LINE;
  1588.         W := WMAX;
  1589.       end if;
  1590.       Z := EXP(W);
  1591.       RESULT := Z + V_OVER_2_MINUS_1 * Z;
  1592.     end if;
  1593.  
  1594.     return RESULT;
  1595.   end COSH;
  1596.  
  1597.  
  1598.   function TANH(X : FLOAT) return FLOAT is
  1599.     G, W, Y, Z : FLOAT;
  1600.     RESULT : FLOAT;
  1601.     BETA : FLOAT := CONVERT_TO_FLOAT(IBETA);
  1602.     EPSILON : FLOAT := BETA ** (-IT/2);
  1603.  
  1604.     XBIG : FLOAT := (LOG(2.0) + CONVERT_TO_FLOAT(IT + 1) * LOG(BETA))/2.0;
  1605.     LN_3_OVER_2 : FLOAT :=  0.54930_61443_34054_84570;
  1606.  
  1607.     function R(G : FLOAT) return FLOAT is
  1608.     P0 : constant FLOAT := -0.21063_95800_0245E2;
  1609.     P1 : constant FLOAT := -0.93363_47565_2401;
  1610.     Q0 : constant FLOAT :=  0.63191_87401_5582E2;
  1611.     Q1 : constant FLOAT :=  0.28077_65347_0471E2;
  1612.     Q2 : constant FLOAT :=  1.0;
  1613.     begin
  1614.       return ((P1*G + P0)*G) / ((G + Q1)*G + Q0);
  1615.     end R;
  1616.  
  1617.   begin
  1618.     Y := ABS(X);
  1619.  
  1620.     if Y > XBIG  then
  1621.       RESULT := 1.0;
  1622.     else
  1623.       if Y > LN_3_OVER_2  then
  1624.         RESULT := 0.5 - 1.0 / (EXP(Y + Y) + 1.0);
  1625.         RESULT := RESULT + RESULT;
  1626.       else
  1627.         if Y < EPSILON  then
  1628.           RESULT := Y;
  1629.         else
  1630.           G := Y * Y;
  1631.           RESULT := Y + Y * R(G);
  1632.         end if;
  1633.       end if;
  1634.     end if;
  1635.     if X < 0.0  then
  1636.       RESULT := - RESULT;
  1637.     end if;
  1638.  
  1639.     return RESULT;
  1640.   end TANH;
  1641.  
  1642.  
  1643. begin
  1644.   null;
  1645. end TRIG_FUNCTIONS;
  1646.