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

  1.  
  2. with Text_Io;
  3. generic
  4.     type Floating is digits <>;
  5. package Generic_Math_Functions is
  6.     use Text_Io;
  7.     Pi        : constant := 3.14159_26535_89793_23846_26433_83279_50288_41972;
  8.     E         : constant := 2.71828_18284_59045_23536_02874_71352_66249_77572;
  9.     Log_Of_2  : constant := 0.69314_71805_59945_30941_72321_24158_17656_80755;
  10.     Log_Of_10 : constant := 2.30258_50929_94045_68401_77914_54684_36420_76011;
  11.     type Error_Response is 
  12.         (Return_Default, 
  13.          Return_Default_And_Log, 
  14.          Raise_Math_Function_Exception, 
  15.          Propagate_Exception);
  16.     What_To_Do_When_There_Is_An_Error : 
  17.         Error_Response := Return_Default_And_Log;
  18.     Math_Function_Exception           : exception;
  19.     Error_Log : Text_Io.File_Type;
  20.     function Sign (X, Y : Floating) return Floating;
  21. --  Returns the value of X with the sign of Y
  22.     function Max (X, Y : Floating) return Floating;
  23. --  Returns the algebraicly larger of X and Y
  24.     function Min (X, Y : Floating) return Floating;
  25. --  Returns the algebraicly smaller of X and Y
  26.     function Truncate (X : Floating) return Floating;
  27. --  Returns the floating value of the integer no larger than X
  28. --  Truncates toward zero
  29.     function Round (X : Floating) return Floating;
  30. --  Returns the floating value of the integer nearest X
  31.     procedure Set_Ran_Key (K : in Floating := Floating (0.0));
  32. --  Can reset the random number generator
  33.     function Ran return Floating;
  34. --  A random number between zero and one
  35.     function Sqrt (X : Floating) return Floating;
  36.     function Cbrt (X : Floating) return Floating;
  37.     function Log (X : Floating) return Floating;
  38.     function Log10 (X : Floating) return Floating;
  39.     function Exp (X : Floating) return Floating;
  40.     function "**" (X, Y : Floating) return Floating;
  41.     function Sin (X : Floating) return Floating;
  42.     function Cos (X : Floating) return Floating;
  43.     function Tan (X : Floating) return Floating;
  44.     function Cot (X : Floating) return Floating;
  45.     function Asin (X : Floating) return Floating;
  46.     function Acos (X : Floating) return Floating;
  47.     function Atan (X : Floating) return Floating;
  48.     function Atan2 (V, U : Floating) return Floating;
  49.     function Sinh (X : Floating) return Floating;
  50.     function Cosh (X : Floating) return Floating;
  51.     function Tanh (X : Floating) return Floating;
  52. end Generic_Math_Functions;
  53. with Text_Io;
  54. package body Generic_Math_Functions is
  55. --  The purpose of this package is to provide a portable Ada facility
  56. --  for new installations, considerable optimization could be done 
  57. --  for particular machines or if fewer functions were required or if
  58. --  error reporting were eliminated or exceptions suppressed 
  59. --  The routines herein are fairly machine-independent, safe, and
  60. --  accurate to about digits 18
  61. --  Each routine is stand-alone from the others - they do not share fragments
  62. --  but LOG10 uses LOG, ATAN2 uses TAN, and SINH, COSH, TANH uses EXP 
  63. --  and LOG and EXP are used in constants
  64. --  Test routines are also available
  65. --  The following routines are coded directly from the algorithms and
  66. --  coeficients given in "Software Manual for the Elementry Functions"
  67. --  by William J. Cody, Jr. and William Waite, Prentice_Hall, 1980
  68. --  CBRT by analogy
  69. --      16 JULY 1982       W A WHITAKER  AFATL EGLIN AFB FL 32542
  70. --                         T C EICHOLTZ  USAFA
  71. --      30  APRIL1986      UPDATED FOR MODERN COMPILERS - WHITAKER
  72.     package Integer_Io is new Text_Io.Integer_Io (Integer);
  73.     package Floating_Io is new Text_Io.Float_Io (Floating);
  74.     package Boolean_Io is new Text_Io.Enumeration_Io (Boolean);
  75.     use Text_Io;
  76. --  The following constants are used in the functions
  77.     One           : constant Floating := Floating (1.0);
  78.     Zero          : constant Floating := One - One;
  79.     Half          : constant Floating := One / (One + One);
  80.     One_Over_Pi   : constant Floating := One / Pi;
  81.     Two_Over_Pi   : constant Floating := (One + One) / Pi;
  82.     Pi_Over_Two   : constant Floating := Pi / (One + One);
  83.     Pi_Over_Three : constant Floating := Pi / (One + One + One);
  84.     Pi_Over_Four  : constant Floating := Pi / (One + One + One + One);
  85.     Beta          : Floating;
  86.     Epsilon       : Floating;
  87.     Ymax          : Floating;
  88.     Exp_Large     : Floating;
  89.     Exp_Small     : Floating;
  90. --  These are included so that the package can be stand-alone and still
  91. --  put out diagnostics on errors
  92.     procedure Put (File : in File_Type; Item : in Integer; 
  93.                    Width : in Field := Integer_Io.Default_Width; 
  94.                    Base : in Number_Base := Integer_Io.Default_Base)
  95.                    renames Integer_Io.Put;
  96.     procedure Put (Item : in Integer; 
  97.                    Width : in Field := Integer_Io.Default_Width; 
  98.                    Base : in Number_Base := Integer_Io.Default_Base)
  99.                    renames Integer_Io.Put;
  100.     procedure Put (File : in File_Type; Item : in Floating; 
  101.                    Fore : in Field := Floating_Io.Default_Fore; 
  102.                    Aft : in Field := Floating_Io.Default_Aft; 
  103.                    Exp : in Field := Floating_Io.Default_Exp)
  104.                    renames Floating_Io.Put;
  105.     procedure Put (Item : in Floating; 
  106.                    Fore : in Field := Floating_Io.Default_Fore; 
  107.                    Aft : in Field := Floating_Io.Default_Aft; 
  108.                    Exp : in Field := Floating_Io.Default_Exp)
  109.                    renames Floating_Io.Put;
  110.     package Floating_Characteristics is
  111. --  This package is a floating mantissa definition of a binary floating
  112. --  The parameters are obtained by initializing on the actual hardware
  113. --  Otherwise the parameters could be set in the spec if known
  114. --  The constants are those required by the routines described in
  115. --  "Software Manual for the Elementary Functions" W. Cody & W. Waite
  116. --  Prentice-Hall 1980
  117. --  Actually most are needed only for the test programs
  118. --  rather than the functions themselves and are reproduced there
  119. --  Many of these could be in the form of attributes for hardware float types
  120. --  but some are not easily available for the machine hardware base
  121. --  So we use the Cody-Waite names and derive them from an adaptation of the
  122. --  MACHAR routine as given by Cody-Waite in Appendix B
  123.         Ibeta  : Integer;
  124. --  The radix of the floating-point representation
  125.         It     : Integer;
  126. --  The number of base IBETA digits in the DIS_floating significand
  127.         Irnd   : Integer;
  128. --  TRUE (1) if floating addition rounds, FALSE (0) if truncates
  129.         Ngrd   : Integer;
  130. --  Number of guard digits for multiplication
  131.         Machep : Integer;
  132. --  The largest negative integer such that
  133. --    1.0 + floating(IBETA) ** MACHEP /= 1.0
  134. --  except that MACHEP is bounded below by -(IT + 3)
  135.         Negep  : Integer;
  136. --  The largest negative integer such that
  137. --    1.0 -0 floating(IBETA) ** NEGEP /= 1.0
  138. --  except that NEGEP is bounded below by -(IT + 3)
  139.         Iexp   : Integer;
  140. --  The number of bits (decimal places if IBETA = 10)
  141. --  reserved for the representation of the exponent (including
  142. --  the bias or sign) of a floating-point number
  143.         Minexp : Integer;
  144. --  The largest in magnitude negative integer such that
  145. --  floating(IBETA) ** MINEXP is a positive floating-point number
  146.         Maxexp : Integer;
  147. --  The largest positive exponent for a finite floating-point number
  148.         Eps    : Floating;
  149. --  The smallest positive floating-point number such that
  150. --                              1.0 + EPS /= 1.0
  151. --  In particular, if IBETA = 2 or IRND = 0,
  152. --  EPS = floating(IBETA) ** MACHEP
  153. --  Otherwise, EPS = (floating(IBETA) ** MACHEP) / 2
  154.         Epsneg : Floating;
  155. --  A small positive floating-poin number such that 1.0-EPSNEG /= 1.0
  156.         Xmin   : Floating;
  157. --  The smallest non-vanishing floating-point power of the radix
  158. --  In particular, XMIN = floating(IBETA) ** MINEXP
  159.         Xmax   : Floating;
  160. --  The largest finite floating-point number
  161. --  Here the structure of the floating type is defined
  162. --  I have assumed that the exponent is always some integer form
  163. --  The mantissa can vary, but is floating here
  164. --  Most efficient implementation may require details of the machine hardware
  165. --  In this version the simplest representation is used
  166. --  The mantissa is extracted into a floating and uses the predefined operations
  167.         type Exponent_Type is new Integer;
  168.         type Mantissa_Type is new Floating;
  169.         --  Now we do something strange
  170. --  Since we may not know in the following routines whether the mantissa
  171. --  will be carried as a fixed or floating type, we have to make some
  172. --  provision for dividing by two
  173. --  We cannot use the literals, since FIXED/2.0 and FLOATING/2 will fail
  174. --  We define a type-dependent factor that will work
  175.         Mantissa_Divide_By_2 : constant Mantissa_Type := 1.0 / 2.0;
  176.         Mantissa_Divide_By_3 : constant Mantissa_Type := 1.0 / 3.0;
  177. --  This will work for the MANTISSA_TYPE defined above
  178. --  The alternative of defining an operation "/" to take care of it
  179. --  is too sweeping and would allow unAda-like errors
  180.         Mantissa_Half        : constant Mantissa_Type := 0.5;
  181.         procedure Defloat (X : in Floating; 
  182.                            N : in out Exponent_Type; F : in out Mantissa_Type);
  183.         procedure Refloat (N : in Exponent_Type; F : in Mantissa_Type; 
  184.                            X : in out Floating);
  185.     end Floating_Characteristics;
  186.     package body Floating_Characteristics is
  187. --  This package is a floating mantissa definition of a binary floating
  188.         package Exponent_Io is new Text_Io.Integer_Io (Exponent_Type);
  189.         package Mantissa_Io is new Text_Io.Float_Io (Mantissa_Type);
  190. --  Again we define PUT only so we can do diagnostics in DEFLOAT and REFLOAT
  191.         procedure Put (File : in File_Type; Item : in Exponent_Type; 
  192.                        Width : in Field := Integer_Io.Default_Width; 
  193.                        Base : in Number_Base := Integer_Io.Default_Base)
  194.                        renames Exponent_Io.Put;
  195.         procedure Put (Item : in Exponent_Type; 
  196.                        Width : in Field := Integer_Io.Default_Width; 
  197.                        Base : in Number_Base := Integer_Io.Default_Base)
  198.                        renames Exponent_Io.Put;
  199.         procedure Put (File : in File_Type; Item : in Mantissa_Type; 
  200.                        Fore : in Field := Floating_Io.Default_Fore; 
  201.                        Aft : in Field := Floating_Io.Default_Aft; 
  202.                        Exp : in Field := Floating_Io.Default_Exp)
  203.                        renames Mantissa_Io.Put;
  204.         procedure Put (Item : in Mantissa_Type; 
  205.                        Fore : in Field := Floating_Io.Default_Fore; 
  206.                        Aft : in Field := Floating_Io.Default_Aft; 
  207.                        Exp : in Field := Floating_Io.Default_Exp)
  208.                        renames Mantissa_Io.Put;
  209.         procedure Defloat (X : in Floating; 
  210.                            N : in out Exponent_Type; F : in out Mantissa_Type) is
  211. --  This is admittedly a slow method - but portable - for breaking down
  212. --  a floating point number into its exponent and mantissa
  213. --  Obviously with knowledge of the machine representation
  214. --  it could be replaced with a couple of simple extractions
  215.             Exponent_Length : Integer := Iexp;
  216.             M               : Exponent_Type;
  217.             W, Y, Z         : Floating;
  218.         begin
  219.             N := 0;
  220.             F := 0.0;
  221.             Y := abs (X);
  222.             if Y = 0.0 then
  223.                 return;
  224.             elsif Y < 0.5 then
  225.                 for J in reverse 0..(Exponent_Length - 2) loop
  226. --  Dont want to go all the way to 2.0**(EXPONENT_LENGTH - 1)
  227. --  Since that (or its reciprocal) will overflow if exponent biased
  228. --  Ought to use talbular values rather than compute each time
  229.                     M := Exponent_Type (2 ** J);
  230.                     Z := 1.0 / Floating (2.0) ** Integer (M);
  231.                     W := Y / Z;
  232.                     if W < 1.0 then
  233.                         Y := W;
  234.                         N := N - M;
  235.                     end if;
  236.                 end loop;
  237.             else
  238.                 for J in reverse 0..(Exponent_Length - 2) loop
  239.                     M := Exponent_Type (2 ** J);
  240.                     Z := Floating (2.0) ** Integer (M);
  241.                     W := Y / Z;
  242.                     if W >= 0.5 then
  243.                         Y := W;
  244.                         N := N + M;
  245.                     end if;
  246.                 end loop;
  247.             end if;
  248.         --  And just to clear up any loose ends from biased exponents
  249.             while Y < 0.5 loop
  250.                 Y := Y * 2.0;
  251.                 N := N - 1;
  252.             end loop;
  253.             while Y >= 1.0 loop
  254.                 Y := Y / 2.0;
  255.                 N := N + 1;
  256.             end loop;
  257.             F := Mantissa_Type (Y);
  258.             if X < 0.0 then
  259.                 F := - F;
  260.             end if;
  261.             return;
  262.         exception
  263.             when others => 
  264.                 if What_To_Do_When_There_Is_An_Error = 
  265.                     Return_Default_And_Log then
  266.                     Put (Error_Log, 
  267.                          "Exception raised in FLOATING_CHARACTERISTICS.DEFLOAT  X = ");
  268.                     Put (Error_Log, X);
  269.                     New_Line (Error_Log);
  270.                 elsif What_To_Do_When_There_Is_An_Error = Propagate_Exception then
  271.                     raise Math_Function_Exception;
  272.                 end if;
  273.                 N := 0;
  274.                 F := 0.0;
  275.                 return;
  276.         end Defloat;
  277.         procedure Refloat (N : in Exponent_Type; F : in Mantissa_Type; 
  278.                            X : in out Floating) is
  279. --  Again a brute force method - but portable
  280. --  Watch out near MAXEXP
  281.             M : Integer;
  282.             Y : Floating;
  283.         begin
  284.             if F = 0.0 then
  285.                 X := Zero;
  286.                 return;
  287.             end if;
  288.             M := Integer (N);
  289.             Y := abs (Floating (F));
  290.             while Y < 0.5 loop
  291.                 M := M - 1;
  292.                 if M < Minexp then
  293.                     X := Zero;
  294.                 end if;
  295.                 Y := Y + Y;
  296.                 exit when M <= Minexp;
  297.             end loop;
  298.             if M = Maxexp then
  299.                 M := M - 1;
  300.                 X := Y * 2.0 ** M;
  301.                 X := X * 2.0;
  302.             elsif M <= Minexp + 2 then
  303.                 M := M + 3;
  304.                 X := Y * 2.0 ** M;
  305.                 X := ((X / 2.0) / 2.0) / 2.0;
  306.             else
  307.                 X := Y * 2.0 ** M;
  308.             end if;
  309.             if F < 0.0 then
  310.                 X := - X;
  311.             end if;
  312.             return;
  313.         exception
  314.             when others => 
  315.                 if What_To_Do_When_There_Is_An_Error = Return_Default_And_Log then
  316.                     Put (Error_Log, 
  317.                          "Exception raised in FLOATING_CHARACTERISTICS.REFLOAT  N = ");
  318.                     Put (Error_Log, N);
  319.                     Put (Error_Log, "  F = ");
  320.                     Put (Error_Log, F);
  321.                     New_Line (Error_Log);
  322.                 elsif What_To_Do_When_There_Is_An_Error = Propagate_Exception then
  323.                     raise Math_Function_Exception;
  324.                 end if;
  325.                 X := Zero;
  326.                 return;
  327.         end Refloat;
  328.         procedure Initialize is
  329. --  This initialization is the MACAR routine of Cody and Waite Appendix B.
  330.             A, B, Y, Z           : Floating;
  331.             I, K, Mx, Iz         : Integer;
  332.             Beta, Betam1, Betain : Floating;
  333.         begin
  334.             A := One;
  335.             while (((A + One) - A) - One) = Zero loop
  336.                 A := A + A;
  337.             end loop;
  338.             B := One;
  339.             while ((A + B) - A) = Zero loop
  340.                 B := B + B;
  341.             end loop;
  342.             Ibeta := Integer ((A + B) - A);
  343.             Beta  := Floating (Ibeta);
  344.             It    := 0;
  345.             B     := One;
  346.             while (((B + One) - B) - One) = Zero loop
  347.                 It := It + 1;
  348.                 B  := B * Beta;
  349.             end loop;
  350.             Irnd   := 0;
  351.             Betam1 := Beta - One;
  352.             if ((A + Betam1) - A) /= Zero then
  353.                 Irnd := 1;
  354.             end if;
  355.             Negep  := It + 3;
  356.             Betain := One / Beta;
  357.             A      := One;
  358.             for I in 1..Negep loop
  359.                 exit when I > Negep;
  360.                 A := A * Betain;
  361.             end loop;
  362.             B := A;
  363.             while ((One - A) - One) = Zero loop
  364.                 A     := A * Beta;
  365.                 Negep := Negep - 1;
  366.             end loop;
  367.             Negep  := - Negep;
  368.             Epsneg := A;
  369.             if (Ibeta /= 2) and (Irnd /= 0) then
  370.                 A := (A * (One + A)) / (One + One);
  371.                 if ((One - A) - One) /= Zero then
  372.                     Epsneg := A;
  373.                 end if;
  374.             end if;
  375.             Machep := - It - 3;
  376.             A      := B;
  377.             while ((One + A) - One) = Zero loop
  378.                 A      := A * Beta;
  379.                 Machep := Machep + 1;
  380.             end loop;
  381.             Eps := A;
  382.             if (Ibeta /= 2) and (Irnd /= 0) then
  383.                 A := (A * (One + A)) / (One + One);
  384.                 if ((One + A) - One) /= Zero then
  385.                     Eps := A;
  386.                 end if;
  387.             end if;
  388.             Ngrd := 0;
  389.             if ((Irnd = 0) and ((One + Eps) * One - One) /= Zero) then
  390.                 Ngrd := 1;
  391.             end if;
  392.             Find_Iexp: 
  393.                 declare
  394.                     Y : Floating := 1.0;
  395.                     A : Floating := Betain;
  396.                     I : Integer := 0;
  397.                 begin
  398.                     loop
  399.                         Y := A * A;
  400.                         exit when Y = 0.0;
  401.                         I := I + 1;
  402.                         A := Y;
  403.                     end loop;
  404.                     Iexp := I;
  405.                 end Find_Iexp;
  406.             Find_Smallest: 
  407.                 declare
  408.                     A, Y : Floating := 1.0;
  409.                     I    : Integer := 0;
  410.                 begin
  411.                     loop
  412.                         Y := A / Beta;
  413.                         exit when Y = 0.0;
  414.                         I := I - 1;
  415.                         A := Y;
  416.                     end loop;
  417.                     Minexp := I;
  418.                     Xmin   := A;
  419.                 end Find_Smallest;
  420.             Find_Largest: 
  421.                 declare
  422.                     A, Y : Floating := 1.0;
  423.                     I    : Integer := 1;
  424.                 begin
  425.                     loop
  426.                         Y := A * Beta;
  427.                         I := I + 1;
  428.                         A := Y;
  429.                     end loop;
  430.                 exception
  431.                     when others => 
  432.                         Maxexp := I;
  433.                         Xmax   := A * ((1.0 - Epsneg) * Beta);
  434.                 end Find_Largest;
  435.         end Initialize;
  436.     begin
  437.         Initialize;
  438.     end Floating_Characteristics;
  439.     use Floating_Characteristics;
  440.     function Sign (X, Y : Floating) return Floating is
  441. --  Returns the value of X with the sign of Y
  442.     begin
  443.         if Y >= 0.0 then
  444.             return X;
  445.         else
  446.             return - X;
  447.         end if;
  448.     end Sign;
  449.     function Max (X, Y : Floating) return Floating is
  450.     begin
  451.         if X >= Y then
  452.             return X;
  453.         else
  454.             return Y;
  455.         end if;
  456.     end Max;
  457.     function Min (X, Y : Floating) return Floating is
  458.     begin
  459.         if X <= Y then
  460.             return X;
  461.         else
  462.             return Y;
  463.         end if;
  464.     end Min;
  465.     function Truncate (X : Floating) return Floating is
  466.     --  Optimum code depends on how the system rounds at exact halves
  467.         Z : Floating := Floating (Integer (X));
  468.     begin
  469.         if X = Z then
  470.             return Z;
  471.         else
  472.             if X > Zero then
  473.         --  For instance, you can get into trouble when 1.0E-20 is overwhelmed
  474.         --  by HALF and X - HALF is -HALF and that is "truncated" to -1
  475.         --  so a simple floating (Integer (X - Half)) does not work in all cases
  476.                 if X < Z then
  477.                     return Z - One;
  478.                 else
  479.                     return Z;
  480.                 end if;
  481.             elsif X = Zero then
  482.                 return Zero;
  483.             else
  484.                 if X < Z then
  485.                     return Z;
  486.                 else
  487.                     return Z + One;
  488.                 end if;
  489.             end if;
  490.         end if;
  491.     end Truncate;
  492.     function Round (X : Floating) return Floating is
  493.     begin
  494.         return Floating (Integer (X));
  495.     end Round;
  496.     package Key is
  497.         X : Integer := 10_001;
  498.         Y : Integer := 20_001;
  499.         Z : Integer := 30_001;
  500.     end Key;
  501.     procedure Set_Ran_Key (K : in Floating := Floating (0.0)) is
  502.         Dummy : Floating := 0.0;
  503.     begin
  504.         if K = Zero then
  505.             Key.X := 10_001;
  506.             Key.Y := 20_001;
  507.             Key.Z := 30_001;
  508.         else
  509.             for I in 1..Integer (K - Floating (Integer (abs (K) / 31_247.0) * 
  510.                   31_247.0)) mod 
  511.                   31_247 loop
  512.                 Dummy := Ran;
  513.             end loop;
  514.         end if;
  515.     end Set_Ran_Key;
  516.     function Ran return Floating is
  517. --  This uses a portable algorithm and is included at this point so that 
  518. --  an implementation could take advantage of unique machine characteristics
  519. --  This rectangular random number routine is adapted from a report
  520. --  "A Pseudo-Random Number Generator" by B. A. Wichmann and I. D. Hill
  521. --  NPL Report DNACS XX (to be published)
  522. --  In this stripped version, it is suitable for machines supporting
  523. --  INTEGER at only 16 bits and is portable in Ada
  524.         W : Floating;
  525.     begin
  526.         Key.X := 171 * (Key.X mod 177 - 177) - 2 * (Key.X / 177);
  527.         if Key.X < 0 then
  528.             Key.X := Key.X + 30269;
  529.         end if;
  530.         Key.Y := 172 * (Key.Y mod 176 - 176) - 35 * (Key.Y / 176);
  531.         if Key.Y < 0 then
  532.             Key.Y := Key.Y + 30307;
  533.         end if;
  534.         Key.Z := 170 * (Key.Z mod 178 - 178) - 63 * (Key.Z / 178);
  535.         if Key.Z < 0 then
  536.             Key.Z := Key.Z + 30323;
  537.         end if;
  538.         W := Floating (Key.X) / 30269.0
  539.              + Floating (Key.Y) / 30307.0
  540.              + Floating (Key.Z) / 30323.0;
  541.         return W - Floating (Integer (W - 0.5));
  542.     end Ran;
  543.     function Sqrt (X : Floating) return Floating is
  544.         M, N    : Exponent_Type;
  545.         F, Y    : Mantissa_Type;
  546.         Result  : Floating;
  547.         Sqrt_C1 : constant Mantissa_Type := 0.41731;
  548.         Sqrt_C2 : constant Mantissa_Type := 0.59016;
  549.         Sqrt_C3 : constant Mantissa_Type := 0.70710_67811_86547_52440;
  550.     begin
  551.         if X = Zero then
  552.             Result := Zero;
  553.             return Result;
  554.         elsif X = One then
  555.             Result := One;     --  To get exact SQRT(1.0)
  556.             return Result;
  557.         elsif X < Zero then
  558.             case What_To_Do_When_There_Is_An_Error is
  559.                 when Return_Default => 
  560.                     null;
  561.                 when Return_Default_And_Log => 
  562.                     New_Line (Error_Log);
  563.                     Put (Error_Log, "CALLED SQRT FOR NEGATIVE ARGUMENT   ");
  564.                     Put (Error_Log, X);
  565.                     Put (Error_Log, "   USED ABSOLUTE VALUE");
  566.                 when Raise_Math_Function_Exception => 
  567.                     raise Math_Function_Exception;
  568.                 when Propagate_Exception => 
  569.                     null;
  570.             end case;
  571.             Result := Sqrt (abs (X));
  572.             return Result;
  573.         else
  574.             Defloat (X, N, F);
  575.             Y := Sqrt_C1 + Mantissa_Type (Sqrt_C2 * F);
  576.             if N mod 2 = 1 then
  577.                 Y := Y * Sqrt_C3;
  578.                 F := F * Mantissa_Divide_By_2;
  579.                 N := N + 1;
  580.             end if;
  581.             M := N / 2;
  582. --      Since always looping to 3, unroll the loop
  583.             Y := Mantissa_Type (Floating (Y) + Floating (F) / Floating (Y)) * 
  584.                 Mantissa_Divide_By_2;
  585.             Y := Mantissa_Type (Floating (Y) + Floating (F) / Floating (Y)) * 
  586.                 Mantissa_Divide_By_2;
  587.             Y := Mantissa_Type (Floating (Y) + Floating (F) / Floating (Y)) * 
  588.                 Mantissa_Divide_By_2;
  589.             Refloat (M, Y, Result);
  590.             return Result;
  591.         end if;
  592.     exception
  593.         when others => 
  594.             case What_To_Do_When_There_Is_An_Error is
  595.                 when Return_Default => 
  596.                     null;
  597.                 when Return_Default_And_Log => 
  598.                     New_Line (Error_Log);
  599.                     Put (Error_Log, " EXCEPTION IN SQRT, X = ");
  600.                     Put (Error_Log, X);
  601.                     Put_Line (Error_Log, "  RETURNED 1.0");
  602.                 when Raise_Math_Function_Exception => 
  603.                     raise Math_Function_Exception;
  604.                 when Propagate_Exception => 
  605.                     raise;
  606.             end case;
  607.             return One;
  608.     end Sqrt;
  609.     function Cbrt (X : Floating) return Floating is
  610.         M, N    : Exponent_Type;
  611.         F, Y    : Mantissa_Type;
  612.         Result  : Floating;
  613.         Cbrt_C1 : constant Mantissa_Type := 0.5874009;
  614.         Cbrt_C2 : constant Mantissa_Type := 0.4125990;
  615.         Cbrt_C3 : constant Mantissa_Type := 0.62996_05249;
  616.         Cbrt_C4 : constant Mantissa_Type := 0.79370_05260;
  617.     begin
  618.         if X = Zero then
  619.             Result := Zero;
  620.             return Result;
  621.         else
  622.             Defloat (X, N, F);
  623.             F := abs (F);
  624.             Y := Cbrt_C1 + Mantissa_Type (Cbrt_C2 * F);
  625.             case (N mod 3) is
  626.                 when 0 => 
  627.                     null;
  628.                 when 1 => 
  629.                     Y := Mantissa_Type (Cbrt_C3 * Y);
  630.                     F := F / 4.0;
  631.                     N := N + 2;
  632.                 when 2 => 
  633.                     Y := Mantissa_Type (Cbrt_C4 * Y);
  634.                     F := F / 2.0;
  635.                     N := N + 1;
  636.                 when others => 
  637.                     null;
  638.             end case;
  639.             M := N / 3;
  640.             Y := Y
  641.                  - (Y * Mantissa_Divide_By_3
  642.                  - Mantissa_Type
  643.                  ((F * Mantissa_Divide_By_3) / Mantissa_Type (Y * 
  644.                 Y)));
  645.             Y := Y
  646.                  - (Y * Mantissa_Divide_By_3
  647.                  - Mantissa_Type
  648.                  ((F * Mantissa_Divide_By_3) / Mantissa_Type (Y * 
  649.                 Y)));
  650.             Y := Y
  651.                  - (Y * Mantissa_Divide_By_3
  652.                  - Mantissa_Type
  653.                  ((F * Mantissa_Divide_By_3) / Mantissa_Type (Y * 
  654.                 Y)));
  655.             Y := Y
  656.                  - (Y * Mantissa_Divide_By_3
  657.                  - Mantissa_Type
  658.                  ((F * Mantissa_Divide_By_3) / Mantissa_Type (Y * 
  659.                 Y)));
  660.             if X < Zero then
  661.                 Y := - Y;
  662.             end if;
  663.             Refloat (M, Y, Result);
  664.             return Result;
  665.         end if;
  666.     exception
  667.         when others => 
  668.             Result := One;
  669.             if X < Zero then
  670.                 Result := - One;
  671.             end if;
  672.             New_Line (Error_Log);
  673.             Put (Error_Log, "EXCEPTION IN CBRT, X = ");
  674.             Put (Error_Log, X);
  675.             Put (Error_Log, "  RETURNED  ");
  676.             Put (Error_Log, Result);
  677.             New_Line (Error_Log);
  678.             return Result;
  679.     end Cbrt;
  680.     function Log (X : Floating) return Floating is
  681.         Result        : Floating;
  682.         N             : Exponent_Type;
  683.         Xn            : Floating;
  684.         Y             : Floating;
  685.         F             : Mantissa_Type;
  686.         Z, Zden, Znum : Mantissa_Type;
  687.         C0            : constant Mantissa_Type := 0.70710_67811_86547_52440;
  688.         C1            : constant Floating := 8#0.543#;
  689.         C2            : constant Floating := - 2.12194_44005_46905_82767_9E-4;
  690.         function R (Z : Mantissa_Type) return Mantissa_Type is
  691.             W : Mantissa_Type := Z * Z;
  692.         begin
  693.             if Floating'Base'Digits < 10 then
  694.                 declare
  695.                     A0 : constant Mantissa_Type := - 0.46490_62303_464e+0;
  696.                     A1 : constant Mantissa_Type := 0.13600_95468_621e-1;
  697.                     B0 : constant Mantissa_Type := - 0.55788_73750_242e+1;
  698.                     B1 : constant Mantissa_Type := 0.10000_00000_000e+1;
  699.                 begin
  700.                     return 
  701.                         Z + Z * W * (A0 + A1 * W) / ((B0 + W));
  702.                 end;
  703.             else
  704.                 declare
  705.                     A0 : constant Mantissa_Type := 
  706.                         - 0.64124_94342_37455_81147e+2;
  707.                     A1 : constant Mantissa_Type := 
  708.                         0.16383_94356_30215_34222e+2;
  709.                     A2 : constant Mantissa_Type := 
  710.                         - 0.78956_11288_74912_57267e+0;
  711.                     B0 : constant Mantissa_Type := 
  712.                         - 0.76949_93210_84948_79777e+3;
  713.                     B1 : constant Mantissa_Type := 
  714.                         0.31203_22209_19245_32844e+3;
  715.                     B2 : constant Mantissa_Type := 
  716.                         - 0.35667_97773_90346_46171e+2;
  717.                     B3 : constant Mantissa_Type := 
  718.                         0.10000_00000_00000_00000e+1;
  719.                 begin
  720.                     return 
  721.                         Z + Z * W * (A0 + (A1 + A2 * W) * W) / 
  722.                         (B0 + (B1 + (B2 + W) * W) * W);
  723.                 end;
  724.             end if;
  725.         end R;
  726.     begin
  727.         if X < Zero then
  728.             New_Line (Error_Log);
  729.             Put (Error_Log, "CALLED LOG FOR NEGATIVE ");
  730.             Put (Error_Log, X);
  731.             Put (Error_Log, "   USE ABS => ");
  732.             Result := Log (abs (X));
  733.             Put (Error_Log, Result);
  734.             New_Line (Error_Log);
  735.         elsif X = Zero then
  736.             New_Line (Error_Log);
  737.             Put (Error_Log, "CALLED LOG FOR ZERO ARGUMENT, RETURNED ");
  738.             Result := - Xmax;      --  SUPPOSED TO BE -LARGE
  739.             Put (Error_Log, Result);
  740.             New_Line (Error_Log);
  741.         else
  742.             Defloat (X, N, F);
  743.             Znum := F - Mantissa_Half;
  744.             if F > C0 then
  745.                 Znum := Znum - Mantissa_Half;
  746.                 Zden := F * Mantissa_Divide_By_2 + Mantissa_Half;
  747.             else
  748.                 N    := N - 1;
  749.                 Zden := Znum * Mantissa_Divide_By_2 + Mantissa_Half;
  750.             end if;
  751.             Z := Mantissa_Type (Znum / Zden);
  752.             if N = 0 then
  753.                 Result := Floating (R (Z));
  754.             else
  755.                 Xn     := Floating (N);
  756.                 Result := (Xn * C2 + Floating (R (Z))) + Xn * C1;
  757.             end if;
  758.         end if;
  759.         return Result;
  760.     exception
  761.         when others => 
  762.            New_Line (Error_Log);
  763.             Put (Error_Log, " EXCEPTION IN LOG, X = ");
  764.             Put (Error_Log, X);
  765.             Put (Error_Log, "  RETURNED 0.0");
  766.             New_Line (Error_Log);
  767.             return Zero;
  768.     end Log;
  769.     function Log10 (X : Floating) return Floating is
  770.         Log_Base_10_Of_E : constant Floating := 0.43429_44819_03251_82765;
  771.     begin
  772.         return Log_Base_10_Of_E * Log (X);
  773.     end Log10;
  774.     function Exp (X : Floating) return Floating is
  775.         Result         : Floating;
  776.         N              : Exponent_Type;
  777.         Xg, Xn, X1, X2 : Floating;
  778.         F, G           : Mantissa_Type;
  779.         One_Over_Log_2 : constant Floating := 1.4426_95040_88896_34074;
  780.         C1             : constant Floating := 0.69335_9375;
  781.         C2             : constant Floating := - 2.1219_44400_54690_58277E-4;
  782.         function R (G : Mantissa_Type) return Mantissa_Type is
  783.             Z, Gp, Q : Mantissa_Type;
  784.         begin
  785.             Z := Mantissa_Type (G * G);
  786.             if Floating'Base'Digits < 9 then
  787.      --  Good for IT <30
  788.                 declare
  789.                     P0 : constant Mantissa_Type := 0.24999_99995_0e+0;
  790.                     P1 : constant Mantissa_Type := 0.41602_88626_8e-2;
  791.                     Q0 : constant Mantissa_Type := 0.5;
  792.                     Q1 : constant Mantissa_Type := 0.49987_17877_8e-1;
  793.                 begin
  794.                     Gp := Mantissa_Type ((Mantissa_Type (P1 * Z) + P0) * G);
  795.                     Q  := Mantissa_Type (Q1 * Z) + Q0;
  796.                 end;
  797.             else
  798.                               --  Good for IT < 57
  799.                 declare
  800.                     P0 : constant Mantissa_Type := 0.24999_99999_99999_993e+0;
  801.                     P1 : constant Mantissa_Type := 0.69436_00015_11792_852e-2;
  802.                     P2 : constant Mantissa_Type := 0.16520_33002_68279_130e-4;
  803.                     Q0 : constant Mantissa_Type := 0.5;
  804.                     Q1 : constant Mantissa_Type := 0.55553_86669_69001_188e-1;
  805.                     Q2 : constant Mantissa_Type := 0.49586_28849_05441_294e-3;
  806.                 begin
  807.                     Gp := Mantissa_Type ((Mantissa_Type ((P2 * Z + P1) * Z) + 
  808.                         P0) * G);
  809.                     Q  := Mantissa_Type ((Mantissa_Type (Q2 * Z) + Q1) * Z) + 
  810.                         Q0;
  811.                 end;
  812.             end if;
  813.             return Mantissa_Half + Mantissa_Type (Gp / (Q - Gp));
  814.         end R;
  815.     begin
  816.         if X > Exp_Large then
  817.             New_Line (Error_Log);
  818.             Put (Error_Log, 
  819.                  "  EXP CALLED WITH TOO BIG A POSITIVE ARGUMENT, ");
  820.             Put (Error_Log, X);
  821.             New_Line (Error_Log);
  822.             Put (Error_Log, "   RETURNED XMAX");
  823.             New_Line (Error_Log);
  824.             Result := Xmax;
  825.         elsif X < Exp_Small then
  826.             New_Line (Error_Log);
  827.             Put (Error_Log, 
  828.                  "  EXP CALLED WITH TOO BIG A NEGATIVE ARGUMENT,  ");
  829.             Put (Error_Log, X);
  830.             Put (Error_Log, "    RETURNED ZERO");
  831.             New_Line (Error_Log);
  832.             Result := Zero;
  833.         elsif abs (X) < Eps then
  834.             Result := One;
  835.         else
  836.             N  := Exponent_Type (X * One_Over_Log_2);
  837.             Xn := Floating (N);
  838.             X1 := Round (X);
  839.             X2 := X - X1;
  840.             Xg := ((X1 - Xn * C1) + X2) - Xn * C2;
  841.             G  := Mantissa_Type (Xg);
  842.             N  := N + 1;
  843.             F  := R (G);
  844.             Refloat (N, F, Result);
  845.         end if;
  846.         return Result;
  847.     exception
  848.         when others => 
  849.             New_Line (Error_Log);
  850.             Put (Error_Log, " EXCEPTION IN EXP, X = ");
  851.             Put (Error_Log, X);
  852.             Put (Error_Log, "  RETURNED 1.0");
  853.             New_Line (Error_Log);
  854.             return One;
  855.     end Exp;
  856.     function "**" (X, Y : Floating) return Floating is
  857.         M, N : Exponent_Type;
  858.         G : Mantissa_Type;
  859.         P, Temp, Iw1, I : Integer;
  860.         Z, V, R, U1, U2, W1, W2, W3, Y1, Y2 : Mantissa_Type;
  861.         A1p1 : Mantissa_Type;
  862.         W, Result : Floating;
  863.         K : constant := 0.44269_50408_88963_40736;
  864.         Ibigx : constant Integer := Integer (Truncate (16.0 * Log (Xmax) - 
  865.                                                  1.0));
  866.         Ismallx : constant Integer := Integer (Truncate (16.0 * Log (Xmin) + 
  867.                                                    1.0));
  868.      --  2**(-i/16) from which A1 and A2 are constructed
  869.         B1 : constant := 8#1.00000_00000_00000_00000_00000_00000#;
  870.         B2 : constant := 8#0.75222_57505_22220_66302_61734_72062#;
  871.         B3 : constant := 8#0.72540_30671_75644_41622_73201_32727#;
  872.         B4 : constant := 8#0.70146_33673_02522_47021_04062_61124#;
  873.         B5 : constant := 8#0.65642_37462_55323_53257_20715_15057#;
  874.         B6 : constant := 8#0.63422_21405_21760_44016_17421_53016#;
  875.         B7 : constant := 8#0.61263_45204_25240_66655_64761_25503#;
  876.         B8 : constant := 8#0.57204_24347_65401_41553_72504_02177#;
  877.         B9 : constant := 8#0.55202_36314_77473_63110_21313_73047#;
  878.         B10 : constant := 8#0.53254_07672_44124_12254_31114_01243#;
  879.         B11 : constant := 8#0.51377_32652_33052_11616_50345_72776#;
  880.         B12 : constant := 8#0.47572_46230_11064_10432_66404_42174#;
  881.         B13 : constant := 8#0.46033_76024_30667_05226_75065_32214#;
  882.         B14 : constant := 8#0.44341_72334_72542_16063_30176_55544#;
  883.         B15 : constant := 8#0.42712_70170_76521_36556_33737_10612#;
  884.         B16 : constant := 8#0.41325_30331_74611_03661_23056_22556#;
  885.         B17 : constant := 8#0.40000_00000_00000_00000_00000_00000#;
  886.         function Reduce (V : Floating) return Mantissa_Type is
  887.         begin
  888.             return Mantissa_Type (Integer (16.0 * V)) * 0.0625;
  889.         end Reduce;
  890.     begin
  891.         if X <= Zero then
  892.             if X < Zero then
  893.                 Result := (abs (X)) ** Y;
  894.                 New_Line (Error_Log);
  895.                 Put (Error_Log, "X**Y CALLED WITH X = ");
  896.                 Put (Error_Log, X);
  897.                 New_Line (Error_Log);
  898.                 Put (Error_Log, "USED ABS, RETURNED ");
  899.                 Put (Error_Log, Result);
  900.                 New_Line (Error_Log);
  901.             else
  902.                 if Y <= Zero then
  903.                     if Y = Zero then
  904.                         Result := Zero;
  905.                     else
  906.                         Result := Xmax;
  907.                     end if;
  908.                     New_Line (Error_Log);
  909.                     Put (Error_Log, "X**Y CALLED WITH X = 0, Y = ");
  910.                     Put (Error_Log, Y);
  911.                     New_Line (Error_Log);
  912.                     Put (Error_Log, "RETURNED ");
  913.                     Put (Error_Log, Result);
  914.                     New_Line (Error_Log);
  915.                 else
  916.                     Result := Zero;
  917.                 end if;
  918.             end if;
  919.         else
  920.             Defloat (X, M, G);
  921.             if Floating'Base'Digits < 9 then
  922.                 declare
  923.                     A1 : array (1..17) of Mantissa_Type := 
  924.                         (8#1.00000_0000#, 
  925.                          8#0.75222_5750#, 
  926.                          8#0.72540_3067#, 
  927.                          8#0.70146_3367#, 
  928.                          8#0.65642_3746#, 
  929.                          8#0.63422_2140#, 
  930.                          8#0.61263_4520#, 
  931.                          8#0.57204_2434#, 
  932.                          8#0.55202_3631#, 
  933.                          8#0.53254_0767#, 
  934.                          8#0.51377_3265#, 
  935.                          8#0.47572_4623#, 
  936.                          8#0.46033_7602#, 
  937.                          8#0.44341_7233#, 
  938.                          8#0.42712_7017#, 
  939.                          8#0.41325_3033#, 
  940.                          8#0.40000_0000#);
  941.                     A2 : array (1..8) of Mantissa_Type := 
  942.                         (8#0.00000_00005_22220_66302_61734_72062#, 
  943.                          8#0.00000_00003_02522_47021_04062_61124#, 
  944.                          8#0.00000_00005_21760_44016_17421_53016#, 
  945.                          8#0.00000_00007_65401_41553_72504_02177#, 
  946.                          8#0.00000_00002_44124_12254_31114_01243#, 
  947.                          8#0.00000_00000_11064_10432_66404_42174#, 
  948.                          8#0.00000_00004_72542_16063_30176_55544#, 
  949.                          8#0.00000_00001_74611_03661_23056_22556#);
  950.                 begin
  951.                     P := 1;
  952.                     if G <= A1 (9) then
  953.                         P := 9;
  954.                     end if;
  955.                     if G <= A1 (P + 4) then
  956.                         P := P + 4;
  957.                     end if;
  958.                     if G <= A1 (P + 2) then
  959.                         P := P + 2;
  960.                     end if;
  961.                     Z := ((G - A1 (P + 1)) - A2 ((P + 1) / 2)) / 
  962.                         (G + A1 (P + 1));
  963.                 end;
  964.             else
  965.                 declare
  966.                     A1 : array (1..17) of Mantissa_Type := 
  967.                         (8#1.00000_00000_00000_000#, 
  968.                          8#0.75222_57505_22220_662#, 
  969.                          8#0.72540_30671_75644_416#, 
  970.                          8#0.70146_33673_02522_470#, 
  971.                          8#0.65642_37462_55323_532#, 
  972.                          8#0.63422_21405_21760_440#, 
  973.                          8#0.61263_45204_25240_666#, 
  974.                          8#0.57204_24347_65401_414#, 
  975.                          8#0.55202_36314_77473_630#, 
  976.                          8#0.53254_07672_44124_122#, 
  977.                          8#0.51377_32652_33052_116#, 
  978.                          8#0.47572_46230_11064_104#, 
  979.                          8#0.46033_76024_30667_052#, 
  980.                          8#0.44341_72334_72542_160#, 
  981.                          8#0.42712_70170_76521_364#, 
  982.                          8#0.41325_30331_74611_036#, 
  983.                          8#0.40000_00000_00000_000#);
  984.                     A2 : array (1..8) of Mantissa_Type := 
  985.                         (8#0.00000_00000_00000_00102_61734_72062#, 
  986.                          8#0.00000_00000_00000_00021_04062_61124#, 
  987.                          8#0.00000_00000_00000_00016_17421_53016#, 
  988.                          8#0.00000_00000_00000_00153_72504_02177#, 
  989.                          8#0.00000_00000_00000_00054_31114_01243#, 
  990.                          8#0.00000_00000_00000_00032_66404_42174#, 
  991.                          8#0.00000_00000_00000_00063_30176_55544#, 
  992.                          8#0.00000_00000_00000_00061_23056_22556#);
  993.                 begin
  994.                     P := 1;
  995.                     if G <= A1 (9) then
  996.                         P := 9;
  997.                     end if;
  998.                     if G <= A1 (P + 4) then
  999.                         P := P + 4;
  1000.                     end if;
  1001.                     if G <= A1 (P + 2) then
  1002.                         P := P + 2;
  1003.                     end if;
  1004.                     Z := ((G - A1 (P + 1)) - A2 ((P + 1) / 2)) / 
  1005.                         (G + A1 (P + 1));
  1006.                 end;
  1007.             end if;
  1008.             Z := Z + Z;
  1009.             V := Z * Z;
  1010.             if Floating'Base'Digits < 11 then
  1011.                 declare
  1012.                     P1 : constant := 0.83333_32862_45E-1;
  1013.                     P2 : constant := 0.12506_48500_52E-1;
  1014.                 begin
  1015.                     R := (P2 * V + P1) * V * Z;
  1016.                 end;
  1017.             else
  1018.                 declare
  1019.                     P1 : constant := 0.83333_33333_33332_11405e-1;
  1020.                     P2 : constant := 0.12500_00000_05037_99174e-1;
  1021.                     P3 : constant := 0.22321_42128_59242_58967e-2;
  1022.                     P4 : constant := 0.43445_77567_21631_19635e-3;
  1023.                 begin
  1024.                     R := (((P4 * V + P3) * V + P2) * V + P1) * V * Z;
  1025.                 end;
  1026.             end if;
  1027.             R   := R + K * R;
  1028.             U2  := (R + Z * K) + Z;
  1029.             U1  := Mantissa_Type (Integer (M) * 16 - P) * 0.0625;
  1030.             Y1  := Reduce (Y);
  1031.             Y2  := Mantissa_Type (Y - Floating (Y1));
  1032.             W   := Floating (U2) * Y + Floating (U1 * Y2);
  1033.             W1  := Reduce (W);
  1034.             W2  := Mantissa_Type (W - Floating (W1));
  1035.             W   := Floating (W1 + U1 * Y1);
  1036.             W1  := Reduce (W);
  1037.             W2  := W2 + Mantissa_Type ((W - Floating (W1)));
  1038.             W3  := Reduce (Floating (W2));
  1039.             Iw1 := Integer (Truncate (16.0 * Floating (W1 + W3)));
  1040.             W2  := W2 - W3;
  1041.             if W > Floating (Ibigx) then
  1042.                 Result := Xmax;
  1043.                 New_Line (Error_Log);
  1044.                 Put (Error_Log, "X**Y CALLED  X =");
  1045.                 Put (Error_Log, X);
  1046.                 Put (Error_Log, "   Y =");
  1047.                 Put (Error_Log, Y);
  1048.                 Put (Error_Log, "   TOO LARGE  RETURNED ");
  1049.                 Put (Error_Log, Result);
  1050.                 New_Line (Error_Log);
  1051.             elsif W < Floating (Ismallx) then
  1052.                 Result := Zero;
  1053.                 New_Line (Error_Log);
  1054.                 Put (Error_Log, "X**Y CALLED  X =");
  1055.                 Put (Error_Log, X);
  1056.                 Put (Error_Log, "   Y =");
  1057.                 Put (Error_Log, Y);
  1058.                 Put (Error_Log, "   TOO SMALL  RETURNED ");
  1059.                 Put (Error_Log, Result);
  1060.                 New_Line (Error_Log);
  1061.             else
  1062.                 if W2 > Mantissa_Type (Zero) then
  1063.                     W2  := W2 - 0.0625;
  1064.                     Iw1 := Iw1 + 1;
  1065.                 end if;
  1066.                 if Iw1 < Integer (Zero) then
  1067.                     I := 0;
  1068.                 else
  1069.                     I := 1;
  1070.                 end if;
  1071.                 M := Exponent_Type (I + Iw1 / 16);
  1072.                 P := 16 * Integer (M) - Iw1;
  1073.                 if Floating'Base'Digits < 13 then
  1074.                     declare
  1075.                         Q1 : constant := 0.69314_71805_56341;
  1076.                         Q2 : constant := 0.24022_65061_44710;
  1077.                         Q3 : constant := 0.55504_04881_30765E-1;
  1078.                         Q4 : constant := 0.96162_06595_83789E-2;
  1079.                         Q5 : constant := 0.13052_55159_42810E-2;
  1080.                     begin
  1081.                         Z := ((((Q5 * W2 + Q4) * W2 + Q3) * W2 + Q2)
  1082.                              * W2 + Q1) * W2;
  1083.                     end;
  1084.                 else
  1085.                     declare
  1086.                         Q1 : constant := 0.69314_71805_59945_29629e+0;
  1087.                         Q2 : constant := 0.24022_65069_59095_37056e+0;
  1088.                         Q3 : constant := 0.55504_10866_40855_95326e-1;
  1089.                         Q4 : constant := 0.96181_29059_51724_16964e-2;
  1090.                         Q5 : constant := 0.13333_54131_35857_84703e-2;
  1091.                         Q6 : constant := 0.15400_29044_09897_64601e-3;
  1092.                         Q7 : constant := 0.14928_85268_05956_08186e-4;
  1093.                     begin
  1094.                         Z := ((((((Q7 * W2 + Q6) * W2 + Q5) * W2 + Q4)
  1095.                              * W2 + Q3) * W2 + Q2) * W2 + Q1) * W2;
  1096.                     end;
  1097.                 end if;
  1098.                 if Floating'Base'Digits < 9 then
  1099.                     declare
  1100.                         A1 : array (1..17) of Mantissa_Type := 
  1101.                             (8#1.00000_0000#, 
  1102.                              8#0.75222_5750#, 
  1103.                              8#0.72540_3067#, 
  1104.                              8#0.70146_3367#, 
  1105.                              8#0.65642_3746#, 
  1106.                              8#0.63422_2140#, 
  1107.                              8#0.61263_4520#, 
  1108.                              8#0.57204_2434#, 
  1109.                              8#0.55202_3631#, 
  1110.                              8#0.53254_0767#, 
  1111.                              8#0.51377_3265#, 
  1112.                              8#0.47572_4623#, 
  1113.                              8#0.46033_7602#, 
  1114.                              8#0.44341_7233#, 
  1115.                              8#0.42712_7017#, 
  1116.                              8#0.41325_3033#, 
  1117.                              8#0.40000_0000#);
  1118.                     begin
  1119.                         Z := A1 (P + 1) + (A1 (P + 1) * Z);
  1120.                     end;
  1121.                 else
  1122.                     declare
  1123.                         A1 : array (1..17) of Mantissa_Type := 
  1124.                             (8#1.00000_00000_00000_000#, 
  1125.                              8#0.75222_57505_22220_662#, 
  1126.                              8#0.72540_30671_75644_416#, 
  1127.                              8#0.70146_33673_02522_470#, 
  1128.                              8#0.65642_37462_55323_532#, 
  1129.                              8#0.63422_21405_21760_440#, 
  1130.                              8#0.61263_45204_25240_666#, 
  1131.                              8#0.57204_24347_65401_414#, 
  1132.                              8#0.55202_36314_77473_630#, 
  1133.                              8#0.53254_07672_44124_122#, 
  1134.                              8#0.51377_32652_33052_116#, 
  1135.                              8#0.47572_46230_11064_104#, 
  1136.                              8#0.46033_76024_30667_052#, 
  1137.                              8#0.44341_72334_72542_160#, 
  1138.                              8#0.42712_70170_76521_364#, 
  1139.                              8#0.41325_30331_74611_036#, 
  1140.                              8#0.40000_00000_00000_000#);
  1141.                     begin
  1142.                         Z := A1 (P + 1) + (A1 (P + 1) * Z);
  1143.                     end;
  1144.                 end if;
  1145.                 Refloat (M, Z, Result);
  1146.             end if;
  1147.         end if;
  1148.         return Result;
  1149.     end "**";
  1150.     function Sin (X : Floating) return Floating is
  1151.         Sgn, Y       : Floating;
  1152.         N            : Integer;
  1153.         Xn           : Floating;
  1154.         F, G, X1, X2 : Floating;
  1155.         Result       : Floating;
  1156.         C1           : constant Floating := 8#3.1104#;
  1157.         C2           : constant Floating := - 0.89089_10206_76153_73566_17e-5;
  1158.         function R (G : Floating) return Floating is
  1159.         begin
  1160.             if Floating'Base'Digits < 10 then
  1161.                 declare
  1162.                     R1 : constant := - 0.16666_66660_883e-0;
  1163.                     R2 : constant := 0.83333_30720_556E-2;
  1164.                     R3 : constant := - 0.19840_83282_313E-3;
  1165.                     R4 : constant := 0.27523_97106_775E-5;
  1166.                     R5 : constant := - 0.23868_34640_601E-7;
  1167.                 begin
  1168.                     return ((((R5 * G + R4) * G + R3) * G + R2) * G + R1) * G;
  1169.                 end;
  1170.             else
  1171.                 declare
  1172.                     R1 : constant := - 0.16666_66666_66666_65052e+0;
  1173.                     R2 : constant := 0.83333_33333_33316_50314e-2;
  1174.                     R3 : constant := - 0.19841_26984_12018_40457e-3;
  1175.                     R4 : constant := 0.27557_31921_01527_56119e-5;
  1176.                     R5 : constant := - 0.25052_10679_82745_84544e-7;
  1177.                     R6 : constant := 0.16058_93649_03715_89114e-9;
  1178.                     R7 : constant := - 0.76429_17806_89104_67734e-12;
  1179.                     R8 : constant := 0.27204_79095_78888_46175e-14;
  1180.                 begin
  1181.                     return (((((((R8 * G + R7) * G + R6) * G + R5) * G + R4) * 
  1182.                         G + R3) * G + R2) * G + R1) * G;
  1183.                 end;
  1184.             end if;
  1185.         end R;
  1186.     begin
  1187.         if X < Zero then
  1188.             Sgn := - One;
  1189.             Y   := - X;
  1190.         else
  1191.             Sgn := One;
  1192.             Y   := X;
  1193.         end if;
  1194.         if Y > Ymax then
  1195.             New_Line (Error_Log);
  1196.             Put (Error_Log, 
  1197.                  " SIN CALLED WITH ARGUMENT TOO LARGE FOR ACCURACY ");
  1198.             Put (Error_Log, X);
  1199.             New_Line (Error_Log);
  1200.             begin
  1201.                 N := Integer (Y);
  1202.             exception
  1203.                 when others => 
  1204.                     Put_Line (Error_Log, " MUCH TOO LARGE!  RETURNED ZERO");
  1205.                     return Zero;
  1206.             end;
  1207.         end if;
  1208.         N  := Integer (Y * One_Over_Pi);
  1209.         Xn := Floating (N);
  1210.         if N mod 2 /= 0 then
  1211.             Sgn := - Sgn;
  1212.         end if;
  1213.         X1 := Truncate (abs (X));
  1214.         X2 := abs (X) - X1;
  1215.         F  := ((X1 - Xn * C1) + X2) - Xn * C2;
  1216.         if abs (F) < Epsilon then
  1217.             Result := F;
  1218.         else
  1219.             Result := F + F * R (F * F);
  1220.         end if;
  1221.         return (Sgn * Result);
  1222.     end Sin;
  1223.     function Cos (X : Floating) return Floating is
  1224.         Sgn, Y       : Floating;
  1225.         N            : Integer;
  1226.         Xn           : Floating;
  1227.         F, G, X1, X2 : Floating;
  1228.         Result       : Floating;
  1229.         C1           : constant Floating := 8#3.1104#;
  1230.         C2           : constant Floating := - 0.89089_10206_76153_73566_17e-5;
  1231.         function R (G : Floating) return Floating is
  1232.         begin
  1233.             if Floating'Base'Digits < 10 then
  1234.                 declare
  1235.                     R1 : constant := - 0.16666_66660_883e-0;
  1236.                     R2 : constant := 0.83333_30720_556E-2;
  1237.                     R3 : constant := - 0.19840_83282_313E-3;
  1238.                     R4 : constant := 0.27523_97106_775E-5;
  1239.                     R5 : constant := - 0.23868_34640_601E-7;
  1240.                 begin
  1241.                     return ((((R5 * G + R4) * G + R3) * G + R2) * G + R1) * G;
  1242.                 end;
  1243.             else
  1244.                 declare
  1245.                     R1 : constant := - 0.16666_66666_66666_65052e+0;
  1246.                     R2 : constant := 0.83333_33333_33316_50314e-2;
  1247.                     R3 : constant := - 0.19841_26984_12018_40457e-3;
  1248.                     R4 : constant := 0.27557_31921_01527_56119e-5;
  1249.                     R5 : constant := - 0.25052_10679_82745_84544e-7;
  1250.                     R6 : constant := 0.16058_93649_03715_89114e-9;
  1251.                     R7 : constant := - 0.76429_17806_89104_67734e-12;
  1252.                     R8 : constant := 0.27204_79095_78888_46175e-14;
  1253.                 begin
  1254.                     return (((((((R8 * G + R7) * G + R6) * G + R5) * G + R4) * 
  1255.                         G + 
  1256.                         R3) * G + R2) * G + R1) * G;
  1257.                 end;
  1258.             end if;
  1259.         end R;
  1260.     begin
  1261.         Sgn := 1.0;
  1262.         Y   := abs (X) + Pi_Over_Two;
  1263.         if Y > Ymax then
  1264.             New_Line (Error_Log);
  1265.             Put (Error_Log, 
  1266.                  " COS CALLED WITH ARGUMENT TOO LARGE FOR ACCURACY ");
  1267.             Put (Error_Log, X);
  1268.             New_Line (Error_Log);
  1269.             begin
  1270.                 N := Integer (Y);
  1271.             exception
  1272.                 when others => 
  1273.                     Put_Line (" MUCH TOO LARGE!  RETURNED ONE");
  1274.                     return One;
  1275.             end;
  1276.         end if;
  1277.         N  := Integer (Y * One_Over_Pi);
  1278.         Xn := Floating (N);
  1279.         if N mod 2 /= 0 then
  1280.             Sgn := - Sgn;
  1281.         end if;
  1282.         Xn := Xn - 0.5;          -- TO FORM COS INSTEAD OF SIN
  1283.         X1 := Truncate (abs (X));
  1284.         X2 := abs (X) - X1;
  1285.         F  := ((X1 - Xn * C1) + X2) - Xn * C2;
  1286.         if abs (F) < Epsilon then
  1287.             Result := F;
  1288.         else
  1289.             G      := F * F;
  1290.             Result := F + F * R (G);
  1291.         end if;
  1292.         return (Sgn * Result);
  1293.     end Cos;
  1294.     function Tan (X : Floating) return Floating is
  1295.         Sgn, Y       : Floating;
  1296.         N            : Integer;
  1297.         Xn           : Floating;
  1298.         F, G, X1, X2 : Floating;
  1299.         Result       : Floating;
  1300.         C1           : constant Floating := 8#1.4442#;
  1301.         C2           : constant Floating := - 0.44544_55103_38076_86783_08e-5;
  1302.         function R (G : Floating) return Floating is
  1303.         begin
  1304.             if Floating'Base'Digits < 11 then
  1305.                 declare
  1306.                     P0 : constant Floating := 1.0;
  1307.                     P1 : constant Floating := - 0.11136_14403_566;
  1308.                     P2 : constant Floating := 0.10751_54738_488E-2;
  1309.                     Q0 : constant Floating := 1.0;
  1310.                     Q1 : constant Floating := - 0.44469_47720_281;
  1311.                     Q2 : constant Floating := 0.15973_39213_300E-1;
  1312.                 begin
  1313.                     return ((P2 * G + P1) * G * F + F) / 
  1314.                         (((Q2 * G + Q1) * G + 0.5) + 0.5);
  1315.                 end;
  1316.             else
  1317.                 declare
  1318.                     P0 : constant := 1.0;
  1319.                     P1 : constant := - 0.13338_35000_64219_60681e+0;
  1320.                     P2 : constant := 0.34248_87823_58905_89960e-2;
  1321.                     P3 : constant := - 0.17861_70734_22544_26711e-4;
  1322.                     Q0 : constant := 1.0;
  1323.                     Q1 : constant := - 0.46671_68333_97552_94240e+0;
  1324.                     Q2 : constant := 0.25663_83228_94401_12864e-1;
  1325.                     Q3 : constant := - 0.31181_53190_70100_27307e-3;
  1326.                     Q4 : constant := 0.49819_43399_37865_12270e-6;
  1327.                 begin
  1328.                     return (((P3 * G + P2) * G + P1) * G * F + F) / 
  1329.                         (((((Q4 * G + Q3) * G + Q2) * G + Q1) * G + 0.5) + 0.5);
  1330.                 end;
  1331.             end if;
  1332.         end R;
  1333.     begin
  1334.         Y := abs (X);
  1335.         if Y > Ymax / 2.0 then
  1336.             New_Line (Error_Log);
  1337.             Put (Error_Log, 
  1338.                  " TAN CALLED WITH ARGUMENT TOO LARGE FOR ACCURACY ");
  1339.             Put (Error_Log, X);
  1340.             New_Line (Error_Log);
  1341.             begin
  1342.                 N := Integer (Y);
  1343.             exception
  1344.                 when others => 
  1345.                     Put_Line (" MUCH TOO LARGE!  RETURNED ZERO");
  1346.                     return Zero;
  1347.             end;
  1348.         end if;
  1349.         N  := Integer (X * Two_Over_Pi);
  1350.         Xn := Floating (N);
  1351.         X1 := Truncate (X);
  1352.         X2 := X - X1;
  1353.         F  := ((X1 - Xn * C1) + X2) - Xn * C2;
  1354.         if abs (F) < Epsilon then
  1355.             Result := F;
  1356.         else
  1357.             G      := F * F;
  1358.             Result := R (G);
  1359.         end if;
  1360.         if N mod 2 = 0 then
  1361.             return Result;
  1362.         else
  1363.             return - 1.0 / Result;
  1364.         end if;
  1365.     end Tan;
  1366.     function Cot (X : Floating) return Floating is
  1367.         Sgn, Y       : Floating;
  1368.         N            : Integer;
  1369.         Xn           : Floating;
  1370.         F, G, X1, X2 : Floating;
  1371.         Result       : Floating;
  1372.         Epsilon1     : constant Floating := 1.0 / Xmax;
  1373.         C1           : constant Floating := 8#1.4442#;
  1374.         C2           : constant Floating := - 0.44544_55103_38076_86783_08e-5;
  1375.         function R (G : Floating) return Floating is
  1376.         begin
  1377.             if Floating'Base'Digits < 11 then
  1378.                 declare
  1379.                     P0 : constant Floating := 1.0;
  1380.                     P1 : constant Floating := - 0.11136_14403_566;
  1381.                     P2 : constant Floating := 0.10751_54738_488E-2;
  1382.                     Q0 : constant Floating := 1.0;
  1383.                     Q1 : constant Floating := - 0.44469_47720_281;
  1384.                     Q2 : constant Floating := 0.15973_39213_300E-1;
  1385.                 begin
  1386.                     return ((P2 * G + P1) * G * F + F) / 
  1387.                         (((Q2 * G + Q1) * G + 0.5) + 0.5);
  1388.                 end;
  1389.             else
  1390.                 declare
  1391.                     P0 : constant := 1.0;
  1392.                     P1 : constant := - 0.13338_35000_64219_60681e+0;
  1393.                     P2 : constant := 0.34248_87823_58905_89960e-2;
  1394.                     P3 : constant := - 0.17861_70734_22544_26711e-4;
  1395.                     Q0 : constant := 1.0;
  1396.                     Q1 : constant := - 0.46671_68333_97552_94240e+0;
  1397.                     Q2 : constant := 0.25663_83228_94401_12864e-1;
  1398.                     Q3 : constant := - 0.31181_53190_70100_27307e-3;
  1399.                     Q4 : constant := 0.49819_43399_37865_12270e-6;
  1400.                 begin
  1401.                     return (((P3 * G + P2) * G + P1) * G * F + F) / 
  1402.                         (((((Q4 * G + Q3) * G + Q2) * G + Q1) * G + 0.5) + 0.5);
  1403.                 end;
  1404.             end if;
  1405.         end R;
  1406.     begin
  1407.         Y := abs (X);
  1408.         if Y < Epsilon1 then
  1409.             New_Line (Error_Log);
  1410.             Put (Error_Log, " COT CALLED WITH ARGUMENT TOO NEAR ZERO ");
  1411.             Put (Error_Log, X);
  1412.             New_Line (Error_Log);
  1413.             if X < 0.0 then
  1414.                 return - Xmax;
  1415.             else
  1416.                 return Xmax;
  1417.             end if;
  1418.         end if;
  1419.         if Y > Ymax / 2.0 then
  1420.             New_Line (Error_Log);
  1421.             Put (Error_Log, 
  1422.                  " COT CALLED WITH ARGUMENT TOO LARGE FOR ACCURACY ");
  1423.             Put (Error_Log, X);
  1424.             New_Line (Error_Log);
  1425.         end if;
  1426.         N  := Integer (X * Two_Over_Pi);
  1427.         Xn := Floating (N);
  1428.         X1 := Truncate (X);
  1429.         X2 := X - X1;
  1430.         F  := ((X1 - Xn * C1) + X2) - Xn * C2;
  1431.         if abs (F) < Epsilon then
  1432.             Result := F;
  1433.         else
  1434.             G      := F * F;
  1435.             Result := R (G);
  1436.         end if;
  1437.         if N mod 2 /= 0 then
  1438.             return - Result;
  1439.         else
  1440.             return 1.0 / Result;
  1441.         end if;
  1442.     end Cot;
  1443.     function Asin (X : Floating) return Floating is
  1444.         G, Y   : Floating;
  1445.         Result : Floating;
  1446.         function R (G : Floating) return Floating is
  1447.         begin
  1448.             if Floating'Base'Digits < 11 then
  1449.                 declare
  1450.                     P1 : constant := - 0.27516_55529_0596E1;
  1451.                     P2 : constant := 0.29058_76237_4859E1;
  1452.                     P3 : constant := - 0.59450_14419_3246;
  1453.                     Q0 : constant := - 0.16509_93320_2424E2;
  1454.                     Q1 : constant := 0.24864_72896_9164E2;
  1455.                     Q2 : constant := - 0.10333_86707_2113E2;
  1456.                     Q3 : constant := 1.0;
  1457.                 begin
  1458.                     return (((P3 * G + P2) * G + P1) * G) / 
  1459.                         (((G + Q2) * G + Q1) * G + Q0);
  1460.                 end;
  1461.             else
  1462.                 declare
  1463.                     P1 : constant := - 0.27368_49452_41642_55994e+2;
  1464.                     P2 : constant := 0.57208_22787_78917_31407e+2;
  1465.                     P3 : constant := - 0.39688_86299_75048_77339e+2;
  1466.                     P4 : constant := 0.10152_52223_38064_63645e+2;
  1467.                     P5 : constant := - 0.69674_57344_73506_46411e+0;
  1468.                     Q0 : constant := - 0.16421_09671_44985_60795e+3;
  1469.                     Q1 : constant := 0.41714_43024_82604_12556e+3;
  1470.                     Q2 : constant := - 0.38186_30336_17501_49284e+3;
  1471.                     Q3 : constant := 0.15095_27084_10306_04719e+3;
  1472.                     Q4 : constant := - 0.23823_85915_36702_38830e+2;
  1473.                     Q5 : constant := 1.0;
  1474.                 begin
  1475.                     return (((((P5 * G + P4) * G + P3) * G + P2) * G + P1) * G) / 
  1476.                         (((((G + Q4) * G + Q3) * G + Q2) * G + Q1) * G + Q0);
  1477.                 end;
  1478.             end if;
  1479.         end R;
  1480.     begin
  1481.         Y := abs (X);
  1482.         if Y > Half then
  1483.             if Y > 1.0 then
  1484.                 New_Line (Error_Log);
  1485.                 Put (Error_Log, " ASIN CALLED FOR ");
  1486.                 Put (Error_Log, X);
  1487.                 Put (Error_Log, " (> 1)  TRUNCATED TO 1, CONTINUED");
  1488.                 New_Line (Error_Log);
  1489.                 Y := 1.0;
  1490.             end if;
  1491.             G      := ((0.5 - Y) + 0.5) / 2.0;
  1492.             Y      := - 2.0 * Sqrt (G);
  1493.             Result := Y + Y * R (G);
  1494.             Result := (Pi_Over_Four + Result) + Pi_Over_Four;
  1495.         else
  1496.             if Y < Epsilon then
  1497.                 Result := Y;
  1498.             else
  1499.                 G      := Y * Y;
  1500.                 Result := Y + Y * R (G);
  1501.             end if;
  1502.         end if;
  1503.         if X < 0.0 then
  1504.             Result := - Result;
  1505.         end if;
  1506.         return Result;
  1507.     end Asin;
  1508.     function Acos (X : Floating) return Floating is
  1509.         G, Y   : Floating;
  1510.         Result : Floating;
  1511.         function R (G : Floating) return Floating is
  1512.         begin
  1513.             if Floating'Base'Digits < 11 then
  1514.                 declare
  1515.                     P1 : constant := - 0.27516_55529_0596E1;
  1516.                     P2 : constant := 0.29058_76237_4859E1;
  1517.                     P3 : constant := - 0.59450_14419_3246;
  1518.                     Q0 : constant := - 0.16509_93320_2424E2;
  1519.                     Q1 : constant := 0.24864_72896_9164E2;
  1520.                     Q2 : constant := - 0.10333_86707_2113E2;
  1521.                     Q3 : constant := 1.0;
  1522.                 begin
  1523.                     return (((P3 * G + P2) * G + P1) * G) / 
  1524.                         (((G + Q2) * G + Q1) * G + Q0);
  1525.                 end;
  1526.             else
  1527.                 declare
  1528.                     P1 : constant := - 0.27368_49452_41642_55994e+2;
  1529.                     P2 : constant := 0.57208_22787_78917_31407e+2;
  1530.                     P3 : constant := - 0.39688_86299_75048_77339e+2;
  1531.                     P4 : constant := 0.10152_52223_38064_63645e+2;
  1532.                     P5 : constant := - 0.69674_57344_73506_46411e+0;
  1533.                     Q0 : constant := - 0.16421_09671_44985_60795e+3;
  1534.                     Q1 : constant := 0.41714_43024_82604_12556e+3;
  1535.                     Q2 : constant := - 0.38186_30336_17501_49284e+3;
  1536.                     Q3 : constant := 0.15095_27084_10306_04719e+3;
  1537.                     Q4 : constant := - 0.23823_85915_36702_38830e+2;
  1538.                     Q5 : constant := 1.0;
  1539.                 begin
  1540.                     return (((((P5 * G + P4) * G + P3) * G + P2) * G + P1) * G) / 
  1541.                         (((((G + Q4) * G + Q3) * G + Q2) * G + Q1) * G + Q0);
  1542.                 end;
  1543.             end if;
  1544.         end R;
  1545.     begin
  1546.         Y := abs (X);
  1547.         if Y > Half then
  1548.             if Y > 1.0 then
  1549.                 New_Line (Error_Log);
  1550.                 Put (Error_Log, " ACOS CALLED FOR ");
  1551.                 Put (Error_Log, X);
  1552.                 Put (Error_Log, " (> 1)  TRUNCATED TO 1, CONTINUED");
  1553.                 New_Line (Error_Log);
  1554.                 Y := 1.0;
  1555.             end if;
  1556.             G      := ((0.5 - Y) + 0.5) / 2.0;
  1557.             Y      := - 2.0 * Sqrt (G);
  1558.             Result := Y + Y * R (G);
  1559.             if X < 0.0 then
  1560.                 Result := (Pi_Over_Two + Result) + Pi_Over_Two;
  1561.             else
  1562.                 Result := - Result;
  1563.             end if;
  1564.         else
  1565.             if Y < Epsilon then
  1566.                 Result := Y;
  1567.             else
  1568.                 G      := Y * Y;
  1569.                 Result := Y + Y * R (G);
  1570.             end if;
  1571.             if X < 0.0 then
  1572.                 Result := (Pi_Over_Four + Result) + Pi_Over_Four;
  1573.             else
  1574.                 Result := (Pi_Over_Four - Result) + Pi_Over_Four;
  1575.             end if;
  1576.         end if;
  1577.         return Result;
  1578.     end Acos;
  1579.     function Atan (X : Floating) return Floating is
  1580.         F, G : Floating;
  1581.         type Region is range 0..3;
  1582.         N                : Region;
  1583.         Result           : Floating;
  1584.         Pi_Over_Six      : constant Floating := Pi_Over_Three / (One + One);
  1585.         Sqrt_3           : constant Floating := 1.73205_08075_68877_29353;
  1586.         Sqrt_3_Minus_1   : constant Floating := 0.73205_08075_68877_29353;
  1587.         Two_Minus_Sqrt_3 : constant Floating := 0.26794_91924_31122_70647;
  1588.         function R (G : Floating) return Floating is
  1589.         begin
  1590.             if Floating'Base'Digits < 10 then
  1591.                 declare
  1592.                     P0 : constant Floating := - 0.14400_83448_74E1;
  1593.                     P1 : constant Floating := - 0.72002_68488_98;
  1594.                     Q0 : constant Floating := 0.43202_50389_19E1;
  1595.                     Q1 : constant Floating := 0.47522_25845_99E1;
  1596.                     Q2 : constant Floating := 1.0;
  1597.                 begin
  1598.                     return ((P1 * G + P0) * G) / ((G + Q1) * G + Q0);
  1599.                 end;
  1600.             else
  1601.                 declare
  1602.                     P0 : constant := - 0.13688_76889_41919_26929e+2;
  1603.                     P1 : constant := - 0.20505_85519_58616_51981e+2;
  1604.                     P2 : constant := - 0.84946_24035_13206_83534e+1;
  1605.                     P3 : constant := - 0.83758_29936_81500_59274e+0;
  1606.                     Q0 : constant := 0.41066_30668_25757_81263e+2;
  1607.                     Q1 : constant := 0.86157_34959_71302_42515e+2;
  1608.                     Q2 : constant := 0.59578_43614_25973_44465e+2;
  1609.                     Q3 : constant := 0.15024_00116_00285_76121e+2;
  1610.                     Q4 : constant := 1.0;
  1611.                 begin
  1612.                     return ((((P3 * G + P2) * G + P1) * G + P0) * G) / 
  1613.                         ((((G + Q3) * G + Q2) * G + Q1) * G + Q0);
  1614.                 end;
  1615.             end if;
  1616.         end R;
  1617.     begin
  1618.         F := abs (X);
  1619.         if F > 1.0 then
  1620.             F := 1.0 / F;
  1621.             N := 2;
  1622.         else
  1623.             N := 0;
  1624.         end if;
  1625.         if F > Two_Minus_Sqrt_3 then
  1626.             F := (((Sqrt_3_Minus_1 * F - 0.5) - 0.5) + F) / (Sqrt_3 + F);
  1627.             N := N + 1;
  1628.         end if;
  1629.         if abs (F) < Epsilon then
  1630.             Result := F;
  1631.         else
  1632.             G      := F * F;
  1633.             Result := F + F * R (G);
  1634.         end if;
  1635.         if N > 1 then
  1636.             Result := - Result;
  1637.         end if;
  1638.         case N is
  1639.             when 0 => 
  1640.                 Result := Result;
  1641.             when 1 => 
  1642.                 Result := Pi_Over_Six + Result;
  1643.             when 2 => 
  1644.                 Result := Pi_Over_Two + Result;
  1645.             when 3 => 
  1646.                 Result := Pi_Over_Three + Result;
  1647.         end case;
  1648.         if X < 0.0 then
  1649.             Result := - Result;
  1650.         end if;
  1651.         return Result;
  1652.     end Atan;
  1653.     function Atan2 (V, U : Floating) return Floating is
  1654.         X, Result : Floating;
  1655.     begin
  1656.         if U = 0.0 then
  1657.             if V = 0.0 then
  1658.                 Result := 0.0;
  1659.                 New_Line (Error_Log);
  1660.                 Put (Error_Log, " ATAN2 CALLED WITH 0/0   RETURNED ");
  1661.                 Put (Error_Log, Result);
  1662.                 New_Line (Error_Log);
  1663.             elsif V > 0.0 then
  1664.                 Result := Pi_Over_Two;
  1665.             else
  1666.                 Result := - Pi_Over_Two;
  1667.             end if;
  1668.         else
  1669.             X      := abs (V / U);
  1670. --  If underflow or overflow is detected, go to the exception
  1671.             Result := Atan (X);
  1672.             if U < 0.0 then
  1673.                 Result := Pi - Result;
  1674.             end if;
  1675.             if V < 0.0 then
  1676.                 Result := - Result;
  1677.             end if;
  1678.         end if;
  1679.         return Result;
  1680.     exception
  1681.         when Numeric_Error => 
  1682.             if abs (V) > abs (U) then
  1683.                 Result := Pi_Over_Two;
  1684.                 if V < 0.0 then
  1685.                     Result := - Result;
  1686.                 end if;
  1687.             else
  1688.                 Result := 0.0;
  1689.                 if U < 0.0 then
  1690.                     Result := Pi - Result;
  1691.                 end if;
  1692.             end if;
  1693.             return Result;
  1694.     end Atan2;
  1695.     function Sinh (X : Floating) return Floating is
  1696.         G, W, Y, Z       : Floating;
  1697.         Result           : Floating;
  1698.         Ybar             : constant Floating := Exp_Large;
  1699.         Ln_V             : constant Floating := 8#0.542714#;
  1700.         V_Over_2_Minus_1 : constant Floating := 0.13830_27787_96019_02638E-4;
  1701.         Wmax             : constant Floating := Ybar - Ln_V + 0.69;
  1702.         function R (G : Floating) return Floating is
  1703.         begin
  1704.             if Floating'Base'Digits < 13 then
  1705.                 declare
  1706.                     P0 : constant Floating := 0.10622_28883_7151E4;
  1707.                     P1 : constant Floating := 0.31359_75645_6058E2;
  1708.                     P2 : constant Floating := 0.34364_14035_8506;
  1709.                     Q0 : constant Floating := 0.63733_73302_1822E4;
  1710.                     Q1 : constant Floating := - 0.13051_01250_9199E3;
  1711.                     Q2 : constant Floating := 1.0;
  1712.                 begin
  1713.                     return (((P2 * G + P1) * G + P0) * G) / ((G + Q1) * G + Q0);
  1714.                 end;
  1715.             else
  1716.                 declare
  1717.                     P0 : constant := - 0.35181_28343_01771_17881e+6;
  1718.                     P1 : constant := - 0.11563_52119_68517_68270e+5;
  1719.                     P2 : constant := - 0.16375_79820_26307_51372e+3;
  1720.                     P3 : constant := - 0.78966_12741_73570_99479e+0;
  1721.                     Q0 : constant := - 0.21108_77005_81062_71242e+7;
  1722.                     Q1 : constant := 0.36162_72310_94218_36460e+5;
  1723.                     Q2 : constant := - 0.27773_52311_96507_01667e+3;
  1724.                     Q3 : constant := 1.0;
  1725.                 begin
  1726.                     return ((((P3 * G + P2) * G + P1) * G + P0) * G) / 
  1727.                         (((G + Q2) * G + Q1) * G + Q0);
  1728.                 end;
  1729.             end if;
  1730.         end R;
  1731.     begin
  1732.         Y := abs (X);
  1733.         if Y <= 1.0 then
  1734.             if Y < Epsilon then
  1735.                 Result := X;
  1736.             else
  1737.                 G      := X * X;
  1738.                 Result := X + X * R (G);
  1739.             end if;
  1740.         else
  1741.             if Y <= Ybar then
  1742.                 Z      := Exp (Y);
  1743.                 Result := (Z - 1.0 / Z) / 2.0;
  1744.             else
  1745.                 W := Y - Ln_V;
  1746.                 if W > Wmax then
  1747.                     New_Line (Error_Log);
  1748.                     Put (Error_Log, 
  1749.                          " SINH CALLED WITH TOO LARGE ARGUMENT  ");
  1750.                     Put (Error_Log, X);
  1751.                     Put (Error_Log, " RETURN BIG");
  1752.                     New_Line (Error_Log);
  1753.                     W := Wmax;
  1754.                 end if;
  1755.                 Z      := Exp (W);
  1756.                 Result := Z + V_Over_2_Minus_1 * Z;
  1757.            end if;
  1758.             if X < 0.0 then
  1759.                 Result := - Result;
  1760.             end if;
  1761.         end if;
  1762.         return Result;
  1763.     end Sinh;
  1764.     function Cosh (X : Floating) return Floating is
  1765.         G, W, Y, Z       : Floating;
  1766.         Result           : Floating;
  1767.         Ybar             : constant Floating := Exp_Large;
  1768.         Ln_V             : constant := 8#0.542714#;
  1769.         V_Over_2_Minus_1 : constant := 0.13830_27787_96019_02638E-4;
  1770.         Wmax             : constant Floating := Ybar - Ln_V + 0.69;
  1771.     begin
  1772.         Y := abs (X);
  1773.         if Y <= Ybar then
  1774.             Z      := Exp (Y);
  1775.             Result := (Z + 1.0 / Z) / 2.0;
  1776.         else
  1777.             W := Y - Ln_V;
  1778.             if W > Wmax then
  1779.                 New_Line (Error_Log);
  1780.                 Put (Error_Log, " COSH CALLED WITH TOO LARGE ARGUMENT  ");
  1781.                 Put (Error_Log, X);
  1782.                 Put (Error_Log, " RETURN BIG");
  1783.                 New_Line (Error_Log);
  1784.                 W := Wmax;
  1785.             end if;
  1786.             Z      := Exp (W);
  1787.             Result := Z + V_Over_2_Minus_1 * Z;
  1788.         end if;
  1789.         return Result;
  1790.     end Cosh;
  1791.     function Tanh (X : Floating) return Floating is
  1792.         G, W, Y, Z  : Floating;
  1793.         Result      : Floating;
  1794.         Xbig        : constant Floating := 
  1795.                     (Log (2.0) + Floating (It + 1) * Log (Beta)) / 2.0;
  1796.         Ln_3_Over_2 : constant Floating := 0.54930_61443_34054_84570;
  1797.         function R (G : Floating) return Floating is
  1798.         begin
  1799.             if Floating'Base'Digits < 11 then
  1800.                 declare
  1801.                     P0 : constant Floating := - 0.21063_95800_0245E2;
  1802.                     P1 : constant Floating := - 0.93363_47565_2401;
  1803.                     Q0 : constant Floating := 0.63191_87401_5582E2;
  1804.                     Q1 : constant Floating := 0.28077_65347_0471E2;
  1805.                     Q2 : constant Floating := 1.0;
  1806.                 begin
  1807.                     return ((P1 * G + P0) * G) / ((G + Q1) * G + Q0);
  1808.                 end;
  1809.             else
  1810.                 declare
  1811.                     P0 : constant := - 0.16134_11902_39962_28053e+4;
  1812.                     P1 : constant := - 0.99225_92967_22360_83313e+2;
  1813.                     P2 : constant := - 0.96437_49277_72254_69787e+0;
  1814.                     Q0 : constant := 0.48402_35707_19886_88686e+4;
  1815.                     Q1 : constant := 0.22337_72071_89623_12926e+4;
  1816.                     Q2 : constant := 0.11274_47438_05349_49335e+3;
  1817.                     Q3 : constant := 1.0;
  1818.                 begin
  1819.                     return (((P2 * G + P1) * G + P0) * G) / 
  1820.                         (((G + Q2) * G + Q1) * G + Q0);
  1821.                 end;
  1822.             end if;
  1823.         end R;
  1824.     begin
  1825.         Y := abs (X);
  1826.         if Y > Xbig then
  1827.             Result := 1.0;
  1828.         else
  1829.             if Y > Ln_3_Over_2 then
  1830.                 Result := 0.5 - 1.0 / (Exp (Y + Y) + 1.0);
  1831.                 Result := Result + Result;
  1832.             else
  1833.                 if Y < Epsilon then
  1834.                     Result := Y;
  1835.                 else
  1836.                     G      := Y * Y;
  1837.                     Result := Y + Y * R (G);
  1838.                 end if;
  1839.             end if;
  1840.         end if;
  1841.         if X < 0.0 then
  1842.             Result := - Result;
  1843.         end if;
  1844.         return Result;
  1845.     end Tanh;
  1846. begin
  1847.     Beta      := Floating (Ibeta);
  1848.     Epsilon   := Beta ** (- It / 2);
  1849.     Ymax      := Floating (Integer (Pi * (One + One) ** (It / 2)));
  1850.     Exp_Large := Log (Xmax) * (One - Epsneg);
  1851.     Exp_Small := Log (Xmin) * (One - Epsneg);
  1852.     Set_Ran_Key;         --  Set to the default anyway 
  1853.     if What_To_Do_When_There_Is_An_Error = Return_Default_And_Log then
  1854.         Create (Error_Log, Out_File, Name (Standard_Output));  --  Set default
  1855.     end if;
  1856. end Generic_Math_Functions;
  1857.