home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / adav313.zip / gnat-3_13p-os2-bin-20010916.zip / emx / gnatlib / a-ngcefu.adb < prev    next >
Text File  |  2000-07-19  |  19KB  |  717 lines

  1. ------------------------------------------------------------------------------
  2. --                                                                          --
  3. --                         GNAT RUNTIME COMPONENTS                          --
  4. --                                                                          --
  5. --                     A D A . N U M E R I C S . G C E F                    --
  6. --                                                                          --
  7. --                                 B o d y                                  --
  8. --                                                                          --
  9. --                            $Revision: 1.8 $                              --
  10. --                                                                          --
  11. --          Copyright (C) 1992-1998 Free Software Foundation, Inc.          --
  12. --                                                                          --
  13. -- GNAT is free software;  you can  redistribute it  and/or modify it under --
  14. -- terms of the  GNU General Public License as published  by the Free Soft- --
  15. -- ware  Foundation;  either version 2,  or (at your option) any later ver- --
  16. -- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
  17. -- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
  18. -- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
  19. -- for  more details.  You should have  received  a copy of the GNU General --
  20. -- Public License  distributed with GNAT;  see file COPYING.  If not, write --
  21. -- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
  22. -- MA 02111-1307, USA.                                                      --
  23. --                                                                          --
  24. -- As a special exception,  if other files  instantiate  generics from this --
  25. -- unit, or you link  this unit with other files  to produce an executable, --
  26. -- this  unit  does not  by itself cause  the resulting  executable  to  be --
  27. -- covered  by the  GNU  General  Public  License.  This exception does not --
  28. -- however invalidate  any other reasons why  the executable file  might be --
  29. -- covered by the  GNU Public License.                                      --
  30. --                                                                          --
  31. -- GNAT was originally developed  by the GNAT team at  New York University. --
  32. -- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
  33. --                                                                          --
  34. ------------------------------------------------------------------------------
  35.  
  36. with Ada.Numerics.Generic_Elementary_Functions;
  37.  
  38. package body Ada.Numerics.Generic_Complex_Elementary_Functions is
  39.  
  40.    package Elementary_Functions is new
  41.       Ada.Numerics.Generic_Elementary_Functions (Real'Base);
  42.    use Elementary_Functions;
  43.  
  44.    PI      : constant := 3.14159_26535_89793_23846_26433_83279_50288_41971;
  45.    PI_2    : constant := PI / 2.0;
  46.    Log_Two : constant := 0.69314_71805_59945_30941_72321_21458_17656_80755;
  47.  
  48.    Epsilon                 : Real'Base;
  49.    Square_Root_Epsilon     : Real'Base;
  50.    Inv_Square_Root_Epsilon : Real'Base;
  51.    Root_Root_Epsilon       : Real'Base;
  52.    Log_Inverse_Epsilon_2   : Real'Base;
  53.  
  54.    Complex_Zero : constant Complex := Compose_From_Cartesian (0.0,  0.0);
  55.    Complex_One  : constant Complex := Compose_From_Cartesian (1.0,  0.0);
  56.    Complex_I    : constant Complex := Compose_From_Cartesian (0.0,  1.0);
  57.    Half_Pi      : constant Complex := Compose_From_Cartesian (PI_2, 0.0);
  58.  
  59.    ----------
  60.    -- Sqrt --
  61.    ----------
  62.  
  63.    function Sqrt (X : Complex) return Complex is
  64.       ReX : constant Real'Base := Re (X);
  65.       ImX : constant Real'Base := Im (X);
  66.       XR  : constant Real'Base := abs Re (X);
  67.       YR  : constant Real'Base := abs Im (X);
  68.       R   : Real'Base;
  69.       R_X : Real'Base;
  70.       R_Y : Real'Base;
  71.  
  72.    begin
  73.       --  Deal with pure real case, see (RM G.1.2(39))
  74.  
  75.       if ImX = 0.0 then
  76.          if ReX > 0.0 then
  77.             return
  78.               Compose_From_Cartesian
  79.                 (Sqrt (ReX), 0.0);
  80.  
  81.          elsif ReX = 0.0 then
  82.             return X;
  83.  
  84.          else
  85.             return
  86.               Compose_From_Cartesian
  87.                 (0.0, Real'Copy_Sign (Sqrt (-ReX), ImX));
  88.          end if;
  89.  
  90.       elsif ReX = 0.0 then
  91.          R_X := Sqrt (YR / 2.0);
  92.  
  93.          if ImX > 0.0 then
  94.             return Compose_From_Cartesian (R_X, R_X);
  95.          else
  96.             return Compose_From_Cartesian (R_X, -R_X);
  97.          end if;
  98.  
  99.       else
  100.          R  := Sqrt (XR ** 2 + YR ** 2);
  101.  
  102.          --  If the square of the modulus overflows, try rescaling the
  103.          --  real and imaginary parts. We cannot depend on an exception
  104.          --  being raised on all targets.
  105.  
  106.          if R > Real'Base'Last then
  107.             raise Constraint_Error;
  108.          end if;
  109.  
  110.          --  We are solving the system
  111.  
  112.          --  XR = R_X ** 2 - Y_R ** 2      (1)
  113.          --  YR = 2.0 * R_X * R_Y          (2)
  114.          --
  115.          --  The symmetric solution involves square roots for both R_X and
  116.          --  R_Y, but it is more accurate to use the square root with the
  117.          --  larger argument for either R_X or R_Y, and equation (2) for the
  118.          --  other.
  119.  
  120.          if ReX < 0.0 then
  121.             R_Y := Sqrt (0.5 * (R - ReX));
  122.             R_X := YR / (2.0 * R_Y);
  123.  
  124.          else
  125.             R_X := Sqrt (0.5 * (R + ReX));
  126.             R_Y := YR / (2.0 * R_X);
  127.          end if;
  128.       end if;
  129.  
  130.       if Im (X) < 0.0 then                 -- halve angle, Sqrt of magnitude
  131.          R_Y := -R_Y;
  132.       end if;
  133.       return Compose_From_Cartesian (R_X, R_Y);
  134.  
  135.    exception
  136.       when Constraint_Error =>
  137.  
  138.          --  Rescale and try again.
  139.  
  140.          R := Modulus (Compose_From_Cartesian (Re (X / 4.0), Im (X / 4.0)));
  141.          R_X := 2.0 * Sqrt (0.5 * R + 0.5 * Re (X / 4.0));
  142.          R_Y := 2.0 * Sqrt (0.5 * R - 0.5 * Re (X / 4.0));
  143.  
  144.          if Im (X) < 0.0 then -- halve angle, Sqrt of magnitude
  145.             R_Y := -R_Y;
  146.          end if;
  147.  
  148.          return Compose_From_Cartesian (R_X, R_Y);
  149.    end Sqrt;
  150.  
  151.    ---------
  152.    -- Log --
  153.    ---------
  154.  
  155.    function Log (X : Complex) return Complex is
  156.       ReX : Real'Base;
  157.       ImX : Real'Base;
  158.       Z   : Complex;
  159.  
  160.    begin
  161.       if Re (X) = 0.0 and then Im (X) = 0.0 then
  162.          raise Constraint_Error;
  163.  
  164.       elsif abs (1.0 - Re (X)) < Root_Root_Epsilon
  165.         and then abs Im (X) < Root_Root_Epsilon
  166.       then
  167.          Z := X;
  168.          Set_Re (Z, Re (Z) - 1.0);
  169.  
  170.          return (1.0 - (1.0 / 2.0 -
  171.                        (1.0 / 3.0 - (1.0 / 4.0) * Z) * Z) * Z) * Z;
  172.       end if;
  173.  
  174.       begin
  175.          ReX := Log (Modulus (X));
  176.  
  177.       exception
  178.          when Constraint_Error =>
  179.             ReX := Log (Modulus (X / 2.0)) - Log_Two;
  180.       end;
  181.  
  182.       ImX := Arctan (Im (X), Re (X));
  183.  
  184.       if ImX > PI then
  185.          ImX := ImX - 2.0 * PI;
  186.       end if;
  187.  
  188.       return Compose_From_Cartesian (ReX, ImX);
  189.    end Log;
  190.  
  191.    ---------
  192.    -- Exp --
  193.    ---------
  194.  
  195.    function Exp (X : Complex) return Complex is
  196.       EXP_RE_X : Real'Base := Exp (Re (X));
  197.  
  198.    begin
  199.       return Compose_From_Cartesian (EXP_RE_X * Cos (Im (X)),
  200.                                      EXP_RE_X * Sin (Im (X)));
  201.    end Exp;
  202.  
  203.  
  204.    function Exp (X : Imaginary) return Complex is
  205.       ImX : Real'Base := Im (X);
  206.  
  207.    begin
  208.       return Compose_From_Cartesian (Cos (ImX), Sin (ImX));
  209.    end Exp;
  210.  
  211.    --------
  212.    -- ** --
  213.    --------
  214.  
  215.    function "**" (Left : Complex; Right : Complex) return Complex is
  216.    begin
  217.       if Re (Right) = 0.0
  218.         and then Im (Right) = 0.0
  219.         and then Re (Left)  = 0.0
  220.         and then Im (Left)  = 0.0
  221.       then
  222.          raise Argument_Error;
  223.  
  224.       elsif Re (Left) = 0.0
  225.         and then Im (Left) = 0.0
  226.         and then Re (Right) < 0.0
  227.       then
  228.          raise Constraint_Error;
  229.  
  230.       elsif Re (Left) = 0.0 and then Im (Left) = 0.0 then
  231.          return Left;
  232.  
  233.       elsif Right = Complex_Zero then
  234.          return Complex_One;
  235.  
  236.       elsif Re (Right) = 0.0 and then Im (Right) = 0.0 then
  237.          return 1.0 + Right;
  238.  
  239.       elsif Re (Right) = 1.0 and then Im (Right) = 0.0 then
  240.          return Left;
  241.  
  242.       else
  243.          return Exp (Right * Log (Left));
  244.       end if;
  245.    end "**";
  246.  
  247.    function "**" (Left : Real'Base; Right : Complex) return Complex is
  248.    begin
  249.       if Re (Right) = 0.0 and then Im (Right) = 0.0 and then Left = 0.0 then
  250.          raise Argument_Error;
  251.  
  252.       elsif Left = 0.0 and then Re (Right) < 0.0 then
  253.          raise Constraint_Error;
  254.  
  255.       elsif Left = 0.0 then
  256.          return Compose_From_Cartesian (Left, 0.0);
  257.  
  258.       elsif Re (Right) = 0.0 and then Im (Right) = 0.0 then
  259.          return Complex_One;
  260.  
  261.       elsif Re (Right) = 1.0 and then Im (Right) = 0.0 then
  262.          return Compose_From_Cartesian (Left, 0.0);
  263.  
  264.       else
  265.          return Exp (Log (Left) * Right);
  266.       end if;
  267.    end "**";
  268.  
  269.    function "**" (Left : Complex; Right : Real'Base) return Complex is
  270.    begin
  271.       if Right = 0.0
  272.         and then Re (Left) = 0.0
  273.         and then Im (Left) = 0.0
  274.       then
  275.          raise Argument_Error;
  276.  
  277.       elsif Re (Left) = 0.0
  278.         and then Im (Left) = 0.0
  279.         and then Right < 0.0
  280.       then
  281.          raise Constraint_Error;
  282.  
  283.       elsif Re (Left) = 0.0 and then Im (Left) = 0.0 then
  284.          return Left;
  285.  
  286.       elsif Right = 0.0 then
  287.          return Complex_One;
  288.  
  289.       elsif Right = 1.0 then
  290.          return Left;
  291.  
  292.       else
  293.          return Exp (Right * Log (Left));
  294.       end if;
  295.    end "**";
  296.  
  297.    ---------
  298.    -- Sin --
  299.    ---------
  300.  
  301.    function Sin (X : Complex) return Complex is
  302.    begin
  303.       if abs Re (X) < Square_Root_Epsilon and then
  304.          abs Im (X) < Square_Root_Epsilon then
  305.          return X;
  306.       end if;
  307.  
  308.       return
  309.         Compose_From_Cartesian
  310.           (Sin (Re (X)) * Cosh (Im (X)),
  311.            Cos (Re (X)) * Sinh (Im (X)));
  312.    end Sin;
  313.  
  314.    ---------
  315.    -- Cos --
  316.    ---------
  317.  
  318.    function Cos (X : Complex) return Complex is
  319.    begin
  320.       return
  321.         Compose_From_Cartesian
  322.           (Cos (Re (X))  * Cosh (Im (X)),
  323.            -Sin (Re (X)) * Sinh (Im (X)));
  324.    end Cos;
  325.  
  326.    ---------
  327.    -- Tan --
  328.    ---------
  329.  
  330.    function Tan (X : Complex) return Complex is
  331.    begin
  332.       if abs Re (X) < Square_Root_Epsilon and then
  333.          abs Im (X) < Square_Root_Epsilon
  334.       then
  335.          return X;
  336.  
  337.       elsif Im (X) > Log_Inverse_Epsilon_2 then
  338.          return Complex_I;
  339.  
  340.       elsif Im (X) < -Log_Inverse_Epsilon_2 then
  341.          return -Complex_I;
  342.  
  343.       else
  344.          return Sin (X) / Cos (X);
  345.       end if;
  346.    end Tan;
  347.  
  348.  
  349.    ---------
  350.    -- Cot --
  351.    ---------
  352.  
  353.    function Cot (X : Complex) return Complex is
  354.    begin
  355.       if abs Re (X) < Square_Root_Epsilon and then
  356.          abs Im (X) < Square_Root_Epsilon
  357.       then
  358.          return Complex_One  /  X;
  359.  
  360.       elsif Im (X) > Log_Inverse_Epsilon_2 then
  361.          return -Complex_I;
  362.  
  363.       elsif Im (X) < -Log_Inverse_Epsilon_2 then
  364.          return Complex_I;
  365.       end if;
  366.  
  367.       return Cos (X) / Sin (X);
  368.    end Cot;
  369.  
  370.    ------------
  371.    -- Arcsin --
  372.    ------------
  373.  
  374.    function Arcsin (X : Complex) return Complex is
  375.       Result : Complex;
  376.  
  377.    begin
  378.       if abs Re (X) < Square_Root_Epsilon and then
  379.          abs Im (X) < Square_Root_Epsilon
  380.       then
  381.          return X;
  382.  
  383.       elsif abs Re (X) > Inv_Square_Root_Epsilon or else
  384.             abs Im (X) > Inv_Square_Root_Epsilon
  385.       then
  386.          Result := -Complex_I * (Log (Complex_I * X) + Log (2.0 * Complex_I));
  387.  
  388.          if Im (Result) > PI_2 then
  389.             Set_Im (Result, PI - Im (X));
  390.  
  391.          elsif Im (Result) < -PI_2 then
  392.             Set_Im (Result, -(PI + Im (X)));
  393.          end if;
  394.       end if;
  395.  
  396.       Result := -Complex_I * Log (Complex_I * X + Sqrt (1.0 - X * X));
  397.  
  398.       if Re (X) = 0.0 then
  399.          Set_Re (Result, Re (X));
  400.  
  401.       elsif Im (X) = 0.0 then
  402.          Set_Im (Result, Im (X));
  403.       end if;
  404.  
  405.       return Result;
  406.    end Arcsin;
  407.  
  408.    ------------
  409.    -- Arccos --
  410.    ------------
  411.  
  412.    function Arccos (X : Complex) return Complex is
  413.       Result : Complex;
  414.  
  415.    begin
  416.       if X = Complex_One then
  417.          return Complex_Zero;
  418.  
  419.       elsif abs Re (X) < Square_Root_Epsilon and then
  420.          abs Im (X) < Square_Root_Epsilon
  421.       then
  422.          return Half_Pi - X;
  423.  
  424.       elsif abs Re (X) > Inv_Square_Root_Epsilon or else
  425.             abs Im (X) > Inv_Square_Root_Epsilon
  426.       then
  427.          return -2.0 * Complex_I * Log (Sqrt ((1.0 + X) / 2.0) +
  428.                             Complex_I * Sqrt ((1.0 - X) / 2.0));
  429.       end if;
  430.  
  431.       Result := -Complex_I * Log (X + Complex_I * Sqrt (1.0 - X * X));
  432.  
  433.       if Im (X) = 0.0 then
  434.          Set_Im (Result, Im (X));
  435.       end if;
  436.  
  437.       return Result;
  438.    end Arccos;
  439.  
  440.    ------------
  441.    -- Arctan --
  442.    ------------
  443.  
  444.    function Arctan (X : Complex) return Complex is
  445.    begin
  446.       if abs Re (X) < Square_Root_Epsilon and then
  447.          abs Im (X) < Square_Root_Epsilon
  448.       then
  449.          return X;
  450.  
  451.       else
  452.          return -Complex_I * (Log (1.0 + Complex_I * X)
  453.                             - Log (1.0 - Complex_I * X)) / 2.0;
  454.       end if;
  455.    end Arctan;
  456.  
  457.    ------------
  458.    -- Arccot --
  459.    ------------
  460.  
  461.    function Arccot (X : Complex) return Complex is
  462.       Xt : Complex;
  463.  
  464.    begin
  465.       if abs Re (X) < Square_Root_Epsilon and then
  466.          abs Im (X) < Square_Root_Epsilon
  467.       then
  468.          return Half_Pi - X;
  469.  
  470.       elsif abs Re (X) > 1.0 / Epsilon or else
  471.             abs Im (X) > 1.0 / Epsilon
  472.       then
  473.          Xt := Complex_One  /  X;
  474.  
  475.          if Re (X) < 0.0 then
  476.             Set_Re (Xt, PI - Re (Xt));
  477.             return Xt;
  478.          else
  479.             return Xt;
  480.          end if;
  481.       end if;
  482.  
  483.       Xt := Complex_I * Log ((X - Complex_I) / (X + Complex_I)) / 2.0;
  484.  
  485.       if Re (Xt) < 0.0 then
  486.          Xt := PI + Xt;
  487.       end if;
  488.  
  489.       return Xt;
  490.    end Arccot;
  491.  
  492.    ----------
  493.    -- Sinh --
  494.    ----------
  495.  
  496.    function Sinh (X : Complex) return Complex is
  497.    begin
  498.       if abs Re (X) < Square_Root_Epsilon and then
  499.          abs Im (X) < Square_Root_Epsilon
  500.       then
  501.          return X;
  502.  
  503.       else
  504.          return Compose_From_Cartesian (Sinh (Re (X)) * Cos (Im (X)),
  505.                                         Cosh (Re (X)) * Sin (Im (X)));
  506.       end if;
  507.    end Sinh;
  508.  
  509.    ----------
  510.    -- Cosh --
  511.    ----------
  512.  
  513.    function Cosh (X : Complex) return Complex is
  514.    begin
  515.       return
  516.         Compose_From_Cartesian
  517.           (Cosh (Re (X)) * Cos (Im (X)),
  518.            Sinh (Re (X)) * Sin (Im (X)));
  519.    end Cosh;
  520.  
  521.    ----------
  522.    -- Tanh --
  523.    ----------
  524.  
  525.    function Tanh (X : Complex) return Complex is
  526.    begin
  527.       if abs Re (X) < Square_Root_Epsilon and then
  528.          abs Im (X) < Square_Root_Epsilon
  529.       then
  530.          return X;
  531.  
  532.       elsif Re (X) > Log_Inverse_Epsilon_2 then
  533.          return Complex_One;
  534.  
  535.       elsif Re (X) < -Log_Inverse_Epsilon_2 then
  536.          return -Complex_One;
  537.  
  538.       else
  539.          return Sinh (X) / Cosh (X);
  540.       end if;
  541.    end Tanh;
  542.  
  543.    ----------
  544.    -- Coth --
  545.    ----------
  546.  
  547.    function Coth (X : Complex) return Complex is
  548.    begin
  549.       if abs Re (X) < Square_Root_Epsilon and then
  550.          abs Im (X) < Square_Root_Epsilon
  551.       then
  552.          return Complex_One  /  X;
  553.  
  554.       elsif Re (X) > Log_Inverse_Epsilon_2 then
  555.          return Complex_One;
  556.  
  557.       elsif Re (X) < -Log_Inverse_Epsilon_2 then
  558.          return -Complex_One;
  559.  
  560.       else
  561.          return Cosh (X) / Sinh (X);
  562.       end if;
  563.    end Coth;
  564.  
  565.    -------------
  566.    -- Arcsinh --
  567.    -------------
  568.  
  569.    function Arcsinh (X : Complex) return Complex is
  570.       Result : Complex;
  571.  
  572.    begin
  573.       if abs Re (X) < Square_Root_Epsilon and then
  574.          abs Im (X) < Square_Root_Epsilon
  575.       then
  576.          return X;
  577.  
  578.       elsif abs Re (X) > Inv_Square_Root_Epsilon or else
  579.             abs Im (X) > Inv_Square_Root_Epsilon
  580.       then
  581.          Result := Log_Two + Log (X); -- may have wrong sign
  582.  
  583.          if (Re (X) < 0.0 and Re (Result) > 0.0)
  584.            or else (Re (X) > 0.0 and Re (Result) < 0.0)
  585.          then
  586.             Set_Re (Result, -Re (Result));
  587.          end if;
  588.  
  589.          return Result;
  590.       end if;
  591.  
  592.       Result := Log (X + Sqrt (1.0 + X * X));
  593.  
  594.       if Re (X) = 0.0 then
  595.          Set_Re (Result, Re (X));
  596.       elsif Im  (X) = 0.0 then
  597.          Set_Im (Result, Im  (X));
  598.       end if;
  599.  
  600.       return Result;
  601.    end Arcsinh;
  602.  
  603.    -------------
  604.    -- Arccosh --
  605.    -------------
  606.  
  607.    function Arccosh (X : Complex) return Complex is
  608.       Result : Complex;
  609.  
  610.    begin
  611.       if X = Complex_One then
  612.          return Complex_Zero;
  613.  
  614.       elsif abs Re (X) < Square_Root_Epsilon and then
  615.          abs Im (X) < Square_Root_Epsilon
  616.       then
  617.          Result := Compose_From_Cartesian (-Im (X), -PI_2 + Re (X));
  618.  
  619.       elsif abs Re (X) > Inv_Square_Root_Epsilon or else
  620.             abs Im (X) > Inv_Square_Root_Epsilon
  621.       then
  622.          Result := Log_Two + Log (X);
  623.  
  624.       else
  625.          Result := 2.0 * Log (Sqrt ((1.0 + X) / 2.0) +
  626.                               Sqrt ((X - 1.0) / 2.0));
  627.       end if;
  628.  
  629.       if Re (Result) <= 0.0 then
  630.          Result := -Result;
  631.       end if;
  632.  
  633.       return Result;
  634.    end Arccosh;
  635.  
  636.    -------------
  637.    -- Arctanh --
  638.    -------------
  639.  
  640.    function Arctanh (X : Complex) return Complex is
  641.    begin
  642.       if abs Re (X) < Square_Root_Epsilon and then
  643.          abs Im (X) < Square_Root_Epsilon
  644.       then
  645.          return X;
  646.       else
  647.          return (Log (1.0 + X) - Log (1.0 - X)) / 2.0;
  648.       end if;
  649.    end Arctanh;
  650.  
  651.    --------------
  652.    -- Arctcoth --
  653.    --------------
  654.  
  655.    function Arccoth (X : Complex) return Complex is
  656.       R : Complex;
  657.  
  658.    begin
  659.       if X = Complex_Zero then
  660.          return Compose_From_Cartesian (0.0, PI_2);
  661.  
  662.       elsif abs Re (X) < Square_Root_Epsilon
  663.          and then abs Im (X) < Square_Root_Epsilon
  664.       then
  665.          return PI_2 * Complex_I + X;
  666.  
  667.       elsif abs Re (X) > 1.0 / Epsilon or else
  668.             abs Im (X) > 1.0 / Epsilon
  669.       then
  670.          if Im (X) > 0.0 then
  671.             return Complex_Zero;
  672.          else
  673.             return PI * Complex_I;
  674.          end if;
  675.  
  676.       elsif Im (X) = 0.0 and then Re (X) = 1.0 then
  677.          raise Constraint_Error;
  678.  
  679.       elsif Im (X) = 0.0 and then Re (X) = -1.0 then
  680.          raise Constraint_Error;
  681.       end if;
  682.  
  683.       begin
  684.          R := Log ((1.0 + X) / (X - 1.0)) / 2.0;
  685.  
  686.       exception
  687.          when Constraint_Error =>
  688.             R := (Log (1.0 + X) - Log (X - 1.0)) / 2.0;
  689.       end;
  690.  
  691.       if Im (R) < 0.0 then
  692.          Set_Im (R, PI + Im (R));
  693.       end if;
  694.  
  695.       if Re (X) = 0.0 then
  696.          Set_Re (R, Re (X));
  697.       end if;
  698.  
  699.       return R;
  700.    end Arccoth;
  701.  
  702. begin
  703.    --  Initialize needed pseudo-constants
  704.  
  705.    Epsilon := Real (Real'Model_Epsilon);
  706.  
  707.    while Epsilon / Real (Real'Machine_Radix) + 1.0 /= 1.0 loop
  708.       Epsilon := Epsilon / Real (Real'Machine_Radix);
  709.    end loop;
  710.  
  711.    Square_Root_Epsilon     := Sqrt (Epsilon);
  712.    Inv_Square_Root_Epsilon := 1.0 / Square_Root_Epsilon;
  713.    Root_Root_Epsilon       := Sqrt (Square_Root_Epsilon);
  714.    Log_Inverse_Epsilon_2   := Log (1.0 / Epsilon) / 2.0;
  715.  
  716. end Ada.Numerics.Generic_Complex_Elementary_Functions;
  717.