(*
 * ExtNum - Operations on arbitrary-precision numbers
 * Copyright (C) 1996 Valerie Menissier-Morain
 *               2008 Gabriel Scherer
 *               2008 David Teller
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version,
 * with the special exception on linking described in file LICENSE.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *)


(** Operation on arbitrary-precision numbers.
    
    Numbers (type {!num}) are arbitrary-precision rational numbers,
    plus the special elements [1/0] (infinity) and [0/0] (undefined). 
    
    @author Valerie Menissier-Morain (base module)
    @author Gabriel Scherer
    @author David Teller

    @documents Num
*)

    open Nat
    open Big_int
    open Ratio

    (** The type of numbers. *)
    type num = Num.num =
	Int of int
      | Big_int of big_int
      | Ratio of ratio 

    type t = num

    (** {6 Usual operations}*)
    val zero   : num
    val one    : num
    val neg    : num -> num
    val abs    : num -> num
    val add    : num -> num -> num
    val sub    : num -> num -> num
    val mul    : num -> num -> num
    val div    : num -> num -> num
    val modulo : num -> num -> num
    val pow    : num -> num -> num

    val compare   : num -> num -> int
    val of_int    : int -> num
    val to_int    : num -> int
    val of_float  : float -> num
    val to_float  : num     -> float
    val of_string : string -> num
    val to_string : num -> string
      (** Convert a number to a string, using fractional notation. *)

    val ( + ) : num -> num -> num
    val ( - ) : num -> num -> num
    val ( * ) : num -> num -> num
    val ( / ) : num -> num -> num
    val ( ** ) : num -> num -> num
    val ( <> ) : num -> num -> bool
    val ( >= ) : num -> num -> bool
    val ( <= ) : num -> num -> bool
    val ( > ) : num -> num -> bool
    val ( < ) : num -> num -> bool
    val ( = ) : num -> num -> bool

    val max_num : num -> num -> num
    val min_num : num -> num -> num

    (** {6 Additional operations}*)
    val quo : num -> num -> num
      (**Euclidian divisiom*)

    val square: num -> num
    val succ  : num -> num
    val pred  : num -> num

    val is_integer : num -> bool
      (** [is_integer x] returns [true] if [x] represents an integer value,
	  [false] otherwise *)

    val round : num -> num
    val floor : num -> num
    val ceil  : num -> num

    val approx: num -> num
      (**[approx n] return the integer closest to [n]*)

    val sign  : num -> int
      (** Return [-1], [0] or [1] according to the sign of the argument. *)

    val operations : num BatNumber.numeric

      

    (** {6 Comparisons between numbers} *)
      
    val ( =/ ) : num -> num -> bool
    val ( </ ) : num -> num -> bool
    val ( >/ ) : num -> num -> bool
    val ( <=/ ) : num -> num -> bool
    val ( >=/ ) : num -> num -> bool
    val ( <>/ ) : num -> num -> bool
    val eq_num : num -> num -> bool
    val lt_num : num -> num -> bool
    val le_num : num -> num -> bool
    val gt_num : num -> num -> bool
    val ge_num : num -> num -> bool
      


      
      
    (** {6 Coercions with strings} *)
      


      
    val approx_num_fix : int -> num -> string
      (** See {!Num.approx_num_exp}.*)
      
    val approx_num_exp : int -> num -> string
      (** Approximate a number by a decimal. The first argument is the
	  required precision. The second argument is the number to
	  approximate. {!Num.approx_num_fix} uses decimal notation; the first
	  argument is the number of digits after the decimal point.
	  [approx_num_exp] uses scientific (exponential) notation; the
	  first argument is the number of digits in the mantissa. *)
      


    (** {6 Coercions between numerical types} *)
    val nat_of_num : num -> nat
    val num_of_nat : nat -> num
    val num_of_big_int : big_int -> num
    val big_int_of_num : num -> big_int
    val ratio_of_num : num -> ratio
    val num_of_ratio : ratio -> num
    val float_of_num : num -> float

    (** {6 Boilerplate code}*)

    (** {7 Printing}*)
    val print: 'a BatInnerIO.output -> t -> unit

	(** {6 Submodules grouping all infix operators} *)

	module Infix : sig
	  include BatNumber.Infix with type bat__infix_t = t

      val ( =/ ) : num -> num -> bool
      val ( </ ) : num -> num -> bool
      val ( >/ ) : num -> num -> bool
      val ( <=/ ) : num -> num -> bool
      val ( >=/ ) : num -> num -> bool
      val ( <>/ ) : num -> num -> bool

      val ( +/ ) : num -> num -> num
      val ( -/ ) : num -> num -> num
      val ( */ ) : num -> num -> num
      val ( // ) : num -> num -> num
      val ( **/ ) : num -> num -> num
    end

	module Compare : BatNumber.Compare with type bat__compare_t = t

    (**/**)

    (** {6 Deprecated} *)
	 	  
    val ( +/ ) : num -> num -> num
    val add_num : num -> num -> num
    val minus_num : num -> num
    val ( -/ ) : num -> num -> num
    val sub_num : num -> num -> num
    val ( */ ) : num -> num -> num
    val mult_num : num -> num -> num      
    val square_num : num -> num
    val ( // ) : num -> num -> num
    val div_num : num -> num -> num      
    val quo_num : num -> num -> num
    val mod_num : num -> num -> num
    val ( **/ ) : num -> num -> num
    val power_num : num -> num -> num
    val abs_num : num -> num
    val succ_num : num -> num
    val pred_num : num -> num
    val incr_num : num ref -> unit
    val decr_num : num ref -> unit
    val is_integer_num : num -> bool
      
    val integer_num : num -> num
    val floor_num : num -> num
    val round_num : num -> num
    val ceiling_num : num -> num
    val sign_num : num -> int


    val string_of_num : num -> string
    val num_of_string : string -> num

    val int_of_num : num -> int
    val num_of_int : int -> num
    val compare_num : num -> num -> int


