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

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