with Standard_Natural_Numbers;           use Standard_Natural_Numbers;
with Standard_Integer_Numbers;           use Standard_Integer_Numbers;
with Standard_Floating_Numbers;          use Standard_Floating_Numbers;
with Double_Double_Numbers;              use Double_Double_Numbers;
with Triple_Double_Numbers;              use Triple_Double_Numbers;
with Quad_Double_Numbers;                use Quad_Double_Numbers;
with Penta_Double_Numbers;               use Penta_Double_Numbers;
with Octo_Double_Numbers;                use Octo_Double_Numbers;

package Deca_Double_Numbers is

-- DESCRIPTION :
--   This package defines deca double numbers and the arithmetic
--   to obtain 10 times the precision of the (standard hardware) doubles.

-- ACKNOWLEDGEMENTS :
--   The code is based on QD-2.3.9 (Y. Hida, X.S. Li, and D.H. Bailey),
--   for the parallels with double double and quad double arithmetic.
--   Definitions are based on the code generated by the CAMPARY library.
--   CAMPARY is the CudA Multiple Precision ARithmetic librarY,
--   by Mioara Joldes, Olivier Marty, Jean-Michel Muller,
--   Valentina Popescu and Warwick Tucker. 

  type deca_double is private;

-- CONSTRUCTORS :

  function create ( i : integer ) return deca_double;

  -- DECRIPTION :
  --   Returns the deca double representation of the standard integer i.

  function create ( n : natural32 ) return deca_double;
  function create ( n : natural64 ) return deca_double;

  -- DESCRIPTION :
  --   Returns the deca double representation of the 32-bit or 64-bit
  --   machine natural number n.

  function create ( i : integer32 ) return deca_double;
  function create ( i : integer64 ) return deca_double;

  -- DESCRIPTION :
  --   Returns the deca double representation of the 32-bit or 64-bit
  --   machine integer number i.

  function create ( x : double_float ) return deca_double;

  -- DESCRIPTION :
  --   The most significant part of the deca double on return is x.

  function create ( right_thumb,right_index,right_middle : double_float;
                    right_ring,right_pink : double_float;
                    left_thumb,left_index,left_middle : double_float;
                    left_ring,left_pink : double_float ) return deca_double;

  -- DESCRIPTION :
  --   The ten doubles on input are stored in the deca double in return,
  --   in the given order of significance.

  function "abs" ( x : deca_double ) return deca_double;

  -- DESCRIPTION :
  --   Returns the absolute value of x.

  function AbsVal ( x : deca_double ) return deca_double; -- same as abs

  function floor ( x : deca_double ) return deca_double;

  -- DESCRIPTION :
  --   Returns nearest lower integer to x.

  function nint ( x : deca_double ) return deca_double;

  -- DESCRIPTION :
  --   Returns the nearest integer to x.

-- SELECTORS :

  function thumb_right ( x : deca_double ) return double_float;

  -- DESCRIPTION :
  --   Returns the most significant double of x.

  function index_right ( x : deca_double ) return double_float;

  -- DESCRIPTION :
  --   Returns the second most significant double of x.

  function middle_right ( x : deca_double ) return double_float;

  -- DESCRIPTION :
  --   Returns the third significant double of x.

  function ring_right ( x : deca_double ) return double_float;

  -- DESCRIPTION :
  --   Returns the fourth most significant double of x.

  function pink_right ( x : deca_double ) return double_float;

  -- DESCRIPTION :
  --   Returns the fifth most significant double of x.

  function thumb_left ( x : deca_double ) return double_float;

  -- DESCRIPTION :
  --   Returns the fifth least significant double of x.

  function index_left ( x : deca_double ) return double_float;

  -- DESCRIPTION :
  --   Returns the fourth least significant double of x.

  function middle_left ( x : deca_double ) return double_float;

  -- DESCRIPTION :
  --   Returns the third least significant double of x.

  function ring_left ( x : deca_double ) return double_float;

  -- DESCRIPTION :
  --   Returns the second least significant double of x.

  function pink_left ( x : deca_double ) return double_float;

  -- DESCRIPTION :
  --   Returns the least significant double of x.

-- TYPE CASTS :

  function to_int ( x : deca_double ) return integer32;

  -- DESCRIPTION :
  --   Converts the highest word into a 32-bit integer;

  function to_double ( x : deca_double ) return double_float;

  -- DESCRIPTION :
  --   Returns right_thumb(x).

  function to_double_double ( x : deca_double ) return double_double;

  -- DESCRIPTION :
  --   Returns the double double with the first two significant
  --   doubles of x.

  function to_triple_double ( x : deca_double ) return triple_double;

  -- DESCRIPTION :
  --   Returns the double double with the first three significant
  --   doubles of x.

  function to_quad_double ( x : deca_double ) return quad_double;

  -- DESCRIPTION :
  --   Returns the double double with the first four significant
  --   doubles of x.

  function to_penta_double ( x : deca_double ) return penta_double;

  -- DESCRIPTION :
  --   Returns the double double with the first five significant
  --   doubles of x.

  function to_octo_double ( x : deca_double ) return octo_double;

  -- DESCRIPTION :
  --   Returns the double double with the first eight significant
  --   doubles of x.

-- COMPARISON and COPYING :

  function is_zero ( x : deca_double ) return boolean;

  -- DESCRIPTION :
  --   Returns true if x is zero, returns false otherwise.

  function is_one ( x : deca_double ) return boolean;

  -- DESCRIPTION :
  --   Returns true if x is one, returns false otherwise.

  function is_positive ( x : deca_double ) return boolean;

  -- DESCRIPTION : 
  --   Returns true if x is positive, returns false otherwise.

  function is_negative ( x : deca_double ) return boolean;

  -- DESCRIPTION : 
  --   Returns true if x is negative, returns false otherwise.

  function equal ( x,y : deca_double ) return boolean;
  function equal ( x : deca_double; y : double_float ) return boolean;

  function "<" ( x,y : deca_double ) return boolean;
  function "<" ( x : deca_double; y : double_float ) return boolean;
  function "<" ( x : double_float; y : deca_double ) return boolean;
  function "<=" ( x,y : deca_double ) return boolean;
  function "<=" ( x : deca_double; y : double_float ) return boolean;
  function "<=" ( x : double_float; y : deca_double ) return boolean;

  function ">" ( x,y : deca_double ) return boolean;
  function ">" ( x : deca_double; y : double_float ) return boolean;
  function ">" ( x : double_float; y : deca_double ) return boolean;
  function ">=" ( x,y : deca_double ) return boolean;
  function ">=" ( x : deca_double; y : double_float ) return boolean;
  function ">=" ( x : double_float; y : deca_double ) return boolean;

  procedure copy ( x : in deca_double; y : in out deca_double );

-- ARITHMETICAL FUNCTIONS :

  function "+" ( x,y : deca_double ) return deca_double; -- returns x+y
  function "+" ( x : deca_double; y : double_float ) return deca_double;
  function "+" ( x : double_float; y : deca_double ) return deca_double;
  function "+" ( x : deca_double ) return deca_double;   -- returns copy

  function "-" ( x : deca_double ) return deca_double;   -- returns -x
  function "-" ( x,y : deca_double ) return deca_double; -- returns x-y
  function "-" ( x : deca_double; y : double_float ) return deca_double;
  function "-" ( x : double_float; y : deca_double ) return deca_double;

  function "*" ( x,y : deca_double ) return deca_double; -- returns x*y
  function "*" ( x : deca_double; y : double_float ) return deca_double;
  function "*" ( x : double_float; y : deca_double ) return deca_double;

  function Mul_pwr2 ( x : deca_double; y : double_float ) -- y = 2^k
                    return deca_double;
  procedure Mul_pwr2 ( x : in out deca_double; y : in double_float );
  -- multiplies x with y, where y is a power of 2

  function "/" ( x,y : deca_double ) return deca_double; -- returns x/y
  function "/" ( x : deca_double; y : double_float ) return deca_double;
  function "/" ( x : double_float; y : deca_double ) return deca_double;

  function sqr ( x : deca_double ) return deca_double;   -- returns x*x
  function "**" ( x : deca_double; n : integer ) return deca_double; -- x^n

  function ldexp ( x : deca_double; n : integer ) return deca_double;
  -- returns (2^n)*x
  function "**" ( x,y : deca_double ) return deca_double; -- x^y
  function "**" ( x : deca_double; y : double_float ) return deca_double;

  function exp ( x : deca_double ) return deca_double;   -- returns exp(x)
  function log ( x : deca_double ) return deca_double;   -- natural log
  function log10 ( x : deca_double ) return deca_double; -- decimal log

-- ARITHMETICAL OPERATIONS AS PROCEDURES :

  procedure Add ( x : in out deca_double; y : in deca_double ); -- x := x+y
  procedure Sub ( x : in out deca_double; y : in deca_double ); -- x := x-y
  procedure Min ( x : in out deca_double );                     -- x:= -x
  procedure Mul ( x : in out deca_double; y : in deca_double ); -- x := x*y
  procedure Div ( x : in out deca_double; y : in deca_double ); -- x := x/y

-- DESTRUCTOR :

  procedure clear ( x : in out deca_double ); -- sets x to zero

private

-- DATA STRUCTURE :
--   A deca double is stored as a record of ten doubles,
--   ordered from high to low significance.
--   The naming of the ten doubles follows the typical count
--   of a right handed person, starting with the fingers on the
--   right hand and then moving on to the fingers of the left hand.

  type deca_double is record
    right_thumb : double_float;  -- most significant double
    right_index : double_float;  -- second most significant double
    right_middle : double_float; -- third most significant double
    right_ring : double_float;   -- fourth most significant double
    right_pink : double_float;   -- fifth most significant double
    left_thumb : double_float;   -- fifth least significant double
    left_index : double_float;   -- fourth least significant double
    left_middle : double_float;  -- third least significant double
    left_ring : double_float;    -- second least significant double
    left_pink : double_float;    -- least significant double
  end record;

end Deca_Double_Numbers;
