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

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