--    GMPAda, binding to the Ada Language for the GNU MultiPrecision library.
--    Copyright (C) 2007-2010 Nicolas Boulenguez <nicolas.boulenguez@free.fr>
--
--    This program is free software: you can redistribute it and/or modify
--    it under the terms of the GNU General Public License as published by
--    the Free Software Foundation, either version 3 of the License, or
--    (at your option) any later version.
--
--    This program is distributed in the hope that it will be useful,
--    but WITHOUT ANY WARRANTY; without even the implied warranty of
--    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
--    GNU General Public License for more details.
--
--    You should have received a copy of the GNU General Public License
--    along with this program.  If not, see <http://www.gnu.org/licenses/>.

package GNU_Multiple_Precision.Big_Floats is

   pragma Elaborate_Body;

   function "<"  (Left, Right : Big_Float) return Boolean;
   function "<=" (Left, Right : Big_Float) return Boolean;
   function ">"  (Left, Right : Big_Float) return Boolean;
   function ">=" (Left, Right : Big_Float) return Boolean;
   function "+"   (Right : Big_Float) return Big_Float;
   function "-"   (Right : Big_Float) return Big_Float;
   function "abs" (Right : Big_Float) return Big_Float;
   function "+"   (Left, Right : Big_Float) return Big_Float;
   function "-"   (Left, Right : Big_Float) return Big_Float;
   function "*"   (Left, Right : Big_Float) return Big_Float;
   function "/"   (Left, Right : Big_Float) return Big_Float;
   function "**"  (Left  : Big_Float; Right : Integer) return Big_Float;

   function Image (Arg : Big_Float) return String;
   function Wide_Image (Arg : Big_Float) return Wide_String;
   function Wide_Wide_Image (Arg : Big_Float) return Wide_Wide_String;
   function Value (Item : String) return Big_Float;
   function Wide_Value (Item : Wide_String) return Big_Float;
   function Wide_Wide_Value (Item : Wide_Wide_String) return Big_Float;
   function Max (Left, Right : Big_Float) return Big_Float;
   function Min (Left, Right : Big_Float) return Big_Float;
   Machine_Radix : constant := 2;
   Emin : constant := Integer'First;
   Emax : constant := Integer'Last;
   function Exponent (X : Big_Float) return Integer;
   function Fraction (X : Big_Float) return Big_Float;
   function Compose (Fraction : Big_Float;
                     Exponent : Integer) return Big_Float;
   function Ceiling    (X : Big_Float) return Big_Float;
   function Floor      (X : Big_Float) return Big_Float;
   function Rounding   (X : Big_Float) return Big_Float;
   function Truncation (X : Big_Float) return Big_Float;

   procedure Set_Default_Precision (New_Value : Bit_Count);
   function Default_Precision return Bit_Count;

   function Precision (Op : Big_Float) return Bit_Count;
   procedure Set_Precision (Rop       : in out Big_Float;
                            New_Value : in     Bit_Count);
   procedure Set_Precision_Raw (Rop       : in out Big_Float;
                                New_Value : in     Bit_Count);
   --  Read the documentation carefully before using that function.

   procedure Set (Rop : in out Big_Float;
                  Op  : in     Big_Float);

   procedure Swap (Rop1, Rop2 : in out Big_Float);

   procedure Add
     (Sum              : in out Big_Float;
      Addend1, Addend2 : in     Big_Float);

   procedure Subtract
     (Difference          : in out Big_Float;
      Minuend, Subtrahend : in     Big_Float);

   procedure Multiply
     (Product                  : in out Big_Float;
      Multiplier, Multiplicand : in     Big_Float);

   procedure Divide (Q     : in out Big_Float;
                     N, D  : in     Big_Float);

   procedure Square_Root
     (Root : in out Big_Float;
      U    : in     Big_Float);

   procedure Negate
     (Negated_Operand : in out Big_Float;
      Operand         : in     Big_Float);

   procedure Absolute_Value
     (Rop : in out Big_Float;
      Op  : in     Big_Float);

   procedure Exponentiate (Rop      : in out Big_Float;
                           Base     : in     Big_Float;
                           Exponent : in     Integer);

   procedure Multiply_2_Exp (Rop : in out Big_Float;
                             Op1 : in     Big_Float;
                             Op2 : in     Bit_Count);
   procedure Divide_2_Exp
     (Q : in out Big_Float;
      N : in     Big_Float;
      B : in     Bit_Count);

   function Equals (Op1, Op2 : Big_Float;
                    Op3      : Bit_Count) return Boolean;
   --  Return non-zero if the first op3 bits of op1 and op2 are equal,
   --  zero otherwise. I.e., test if Op1 and Op2 are approximately
   --  equal.  Caution: currently only whole limbs are compared, and
   --  only in an exact fashion. In the future values like 1000 and
   --  0111 may be considered the same to 3 bits (on the basis that
   --  their difference is that small).

   procedure Relative_Difference (Rop      : in out Big_Float;
                                  Op1, Op2 : in     Big_Float);
   --  |op1 - op2|/op1
   function Sign (Item : in Big_Float) return A_Sign;

   procedure Floor
     (Rop : in out Big_Float;
      Op  : in     Big_Float);
   procedure Ceiling
     (Rop : in out Big_Float;
      Op  : in     Big_Float);
   procedure Truncation
     (Rop : in out Big_Float;
      Op  : in     Big_Float);
   function Is_Integer (Op : Big_Float) return Boolean;

   generic
      type Num is range <>;
   package Integer_Conversions is
      procedure Set (Rop : in out Big_Float;
                     Op  : in     Num);
      function To_Big_Float (Item : Num) return Big_Float;
      function Fits_In_Num (Item : Big_Float) return Boolean;
      function To_Num (Item : Big_Float) return Num;
      --  Constraint_Error is raised if not Fits_In_Num (Item).
   private
      pragma Inline (Set);
      pragma Inline (To_Big_Float);
      pragma Inline (Fits_In_Num);
      pragma Inline (To_Num);
   end Integer_Conversions;

   generic
      type Num is mod <>;
   package Modular_Conversions is
      procedure Set (Rop : in out Big_Float;
                     Op  : in     Num);
      function To_Big_Float (Item : Num) return Big_Float;
      function Fits_In_Num (Item : Big_Float) return Boolean;
      function To_Num (Item : Big_Float) return Num;
      --  Constraint_Error is raised if not Fits_In_Num (Item).
   private
      pragma Inline (Set);
      pragma Inline (To_Big_Float);
      pragma Inline (Fits_In_Num);
      pragma Inline (To_Num);
   end Modular_Conversions;

   generic
      type Num is digits <>;
   package Float_Conversions is
      procedure Set (Rop : in out Big_Float;
                     Op  : in     Num);
      function To_Big_Float (Item : Num) return Big_Float;
      function To_Num (Item : Big_Float) return Num;
      procedure Split_Mantissa_Exponent
        (Mantissa :    out Num;
         Exponent :    out Integer;
         Op       : in     Big_Float);
      --  The Mantissa is in The range 0.5<|D|< 1 and
      --  Op = Mantissa * 2 ** Exponent = (Truncated towards 0) Op
      --  Value.  If Op is zero, both are zero.
   private
      pragma Inline (Set);
      pragma Inline (To_Big_Float);
      pragma Inline (To_Num);
      pragma Inline (Split_Mantissa_Exponent);
   end Float_Conversions;

   procedure Set (Rop : in out Big_Integer;
                  Op  : in     Big_Float);

   procedure Set (Rop : in out Big_Float;
                  Op  : in     Big_Integer);

private

   pragma Inline ("<=");
   pragma Inline ("<");
   pragma Inline (">=");
   pragma Inline (">");
   pragma Inline ("-");
   pragma Inline ("/");
   pragma Inline ("*");
   pragma Inline ("**");
   pragma Inline ("+");
   pragma Inline ("abs");
   pragma Inline (Absolute_Value);
   pragma Inline (Add);
   pragma Inline (Ceiling);
   pragma Inline (Compose);
   pragma Inline (Default_Precision);
   pragma Inline (Divide);
   pragma Inline (Divide_2_Exp);
   pragma Inline (Equals);
   pragma Inline (Exponent);
   pragma Inline (Exponentiate);
   pragma Inline (Floor);
   pragma Inline (Fraction);
   pragma Inline (Is_Integer);
   pragma Inline (Max);
   pragma Inline (Min);
   pragma Inline (Multiply);
   pragma Inline (Multiply_2_Exp);
   pragma Inline (Negate);
   pragma Inline (Precision);
   pragma Inline (Relative_Difference);
   pragma Inline (Set);
   pragma Inline (Set_Default_Precision);
   pragma Inline (Set_Precision);
   pragma Inline (Set_Precision_Raw);
   pragma Inline (Sign);
   pragma Inline (Square_Root);
   pragma Inline (Subtract);
   pragma Inline (Swap);
   pragma Inline (Truncation);
   pragma Inline (Wide_Image);
   pragma Inline (Wide_Value);
   pragma Inline (Wide_Wide_Image);
   pragma Inline (Wide_Wide_Value);

end GNU_Multiple_Precision.Big_Floats;
