      IntOperations
      Copyright (c)  2012,2014 John Abbott and Anna M. Bigatti
      GNU Free Documentation License, Version 1.2
%!includeconf: ../aux-txt2tags/config.t2t
      TeXTitle{IntOperations}{John Abbott}


== Examples ==[examples]
%======================================================================
- [ex-BigInt1.C   ../../examples/index.html#ex-BigInt1.C]
- [ex-BigInt2.C   ../../examples/index.html#ex-BigInt2.C]
- [ex-BigInt3.C   ../../examples/index.html#ex-BigInt3.C]
-


== User documentation ==
%======================================================================

Here is a collection of basic operations available for integer values;
see also the more advanced functions in [[NumTheory]].

CoCoALib functions which expect integer values will accept either
machine integer values or [[BigInt]] values -- they may be mixed.  The
return type is usually [[BigInt]]; the few cases where the return type
is ``long`` are clearly indicated.  Remember that basic arithmetic
operations between two machine integers are handled directly by C++
(with its rules and restrictions //e.g.// overflow).

If you want to write new functions which accept machine integers as
arguments, take a look at the class [[MachineInt]] which is designed
for this purpose (handling both signed and unsigned machine integers
safely).



=== Queries ===[queries]
%----------------------------------------------------------------------
- ``IsEven(n)``     -- true iff ``n`` is even
- ``IsOdd(n)``      -- true iff ``n`` is odd
- ``IsPowerOf2(n)`` -- true iff ``n`` is a (positive) power of 2
- ``IsDivisible(n,d)`` -- true iff ``n`` is divisible by ``d`` (throws ``ERR::DivByZero`` if ``d`` is zero)
- ``IsSquare(n)``   -- true iff ``n`` is a perfect square
- ``IsPower(n)``    -- true iff ``n`` is a perfect k-th power for some k > 1
- ``IsExactIroot(X,n,r)`` -- true iff ``n`` is a perfect ``r``-th power, assigns ``iroot(N,r)`` to ``X``
-

Only for [[BigInt]]
- ``IsZero(N)``     -- true iff ``N`` is zero
- ``IsOne(N)``      -- true iff ``N`` is 1
- ``IsMinusOne(N)`` -- true iff ``N`` is -1
-

=== Operations ===[operations]
%----------------------------------------------------------------------

==== Infix operators ====
+ normal arithmetic (potentially inefficient because of temporaries)
 - ``=``    assignment
 - ``+``    the sum
 - ``-``    the difference
 - ``*``    the product
 - ``/``    integer quotient (**truncated** "towards zero")
 - ``%``    remainder, satisfies a = b*(a/b)+(a%b); see also ``LeastNNegRemainder`` and ``SymmRemainder``


**NOTE:**  **you cannot use** ``^`` **for exponentiation**; you must use the function ``power`` instead.  We decided this
because it is too easy to write misleading code: for instance,
``a*b^2`` is interpreted by the compiler as ``(a*b)^2``.  There is no
way to make the C++ compiler use the expected interpretation.


+ arithmetic and assignment
 - ``+=``, ``-=``, ``*=``, ``/=``, ``%=`` 
   --  definitions as expected; if RHS is a [[BigInt]] LHS must be [[BigInt]]

+ arithmetic ordering
 - ``==``, ``!=``
 - ``<``, ``<=``, ``>``, ``>=``
     -- comparison (using the normal arithmetic ordering)
     -- see also the ``cmp`` function below.

+ increment/decrement
 - ``++``, ``--`` (prefix, //e.g.// ``++a``)   use these if you can
 - ``++``, ``--`` (postfix, //e.g.// ``a++``)  avoid these if you can, as they create temporaries



==== cmp ====
(three way comparison)
- ``cmp(a, b)`` -- returns an ``int`` which is
                      ``< 0``,   ``== 0``, or   ``> 0`` if
                    ``a < b``, ``a == b``, or ``a > b`` respectively
- ``CmpAbs(a,b)`` -- same as ``cmp(abs(a),abs(b))`` but might be faster.
-

==== Sundry standard functions ====
(Several basic number theoretical operations are defined in [[NumTheory]])
Let ``n`` be an integer,

- ``abs(n)``         -- the absolute value of ``n``
- ``sign(n)``        -- (returns ``int``) returns
                         -1 if ``n<0``, 0 if ``n==0``, and +1 if ``n>0``
- ``LeastNNegRemainder(x,m)``  -- least non-negative remainder; throws ``ERR::DivByZero`` if ``m==0``
- ``SymmRemainder(x,m)``  -- symmetric remainder; throws ``ERR::DivByZero`` if ``m==0``
- ``log(n)``         -- natural logarithm of the absolute value of ``n`` (as a ``double``)
- ``RoundDiv(n,d)``-- rounded division of ``n`` by ``d``, (currently halves round away from 0)
- ``isqrt(n)``     -- the (truncated) integer part of the square root of ``n``
- ``ILogBase(n,b)``-- (returns ``long``) the integer part of ``log(abs(n))/log(b)``;
                      error if ``n=0`` or ``b<2``
-

These functions return [[BigInt]]
- ``power(a, b)`` -- returns ``a`` to the power ``b`` (error if ``b<0``); ``power(0,0)`` gives 1
- ``SmallPower(a, b)`` -- (returns ``long``) returns ``a`` to the power ``b`` (error if ``b<0``; **no check for overflow**) 
- ``factorial(n)``   -- factorial for non-negative ``n``
- ``LogFactorial(n)``   -- approx natural log of ``factorial(n)`` (abs.err. < 5*10^(-8))
- ``RangeFactorial(lo,hi)`` -- ``lo*(lo+1)*(lo+2)*...*hi``
- ``binomial(n, r)`` -- binomial coefficient
- ``fibonacci(n)``   -- ``n``-th Fibonacci number
- ``iroot(N,r)``     -- the (truncated) integer part of the ``r``-th root of ``N`` (error if ``r<2`` or even root of negative); see also ``IsExactIroot``
- ``RandomBigInt(lo, hi)`` -- a uniform random integer ``N`` s.t. ``lo <= N <=  hi`` (see [[random]] for details).
-

==== Conversion functions ====
Only for [[BigInt]]
- ``mantissa(N)`` -- ``N`` represented as a floating-point number.
  	    If ``N`` is zero, produces 0.0.
            If ``N>0``, produces a value between 0.5 and 0.999...;
            otherwise (when ``N<0``) a value between -0.5 and -0.999...
            The bits of the floating point result are the topmost
            bits of the binary representation of ``N``.
- ``exponent(N)`` -- result is a ``long`` whose value is the least integer e such that
              2^e > abs(n).  If ``N`` is zero, result is zero.
-

==== Miscellany ====
Only for [[BigInt]]
- ``NumDigits(N, b)`` -- (returns ``long``) the number of digits ``N`` has
                         when written in base ``b``
                         (the result may sometimes to be too large by 1)
-

==== Procedures for arithmetic ====

These procedures are ugly but may give a slight gain in speed.
Use them only if you really must; it is probably better to use
GMP directly if speed is so very important.

We expect these procedures (except ``quorem``) to **become obsolete**
when CoCoALib upgrades to the C++11 standard.

Assignment is always to leftmost argument(s) ``a``, a [[BigInt]].
Second and/or third argument of type [[BigInt]].
- ``add(a, b, c)``   --  a = b+c
- ``sub(a, b, c)``   --  a = b-c
- ``mul(a, b, c)``   --  a = b*c
- ``div(a, b, c)``   --  a = b/c  (truncated integer quotient)
- ``mod(a, b, c)``   --  a = b%c  (remainder s.t. b = quot*c + rem)
- ``quorem(a, b, c, d)`` --  same as a = c/d, b = c%d
- ``divexact(a, b, c)`` --  a = b/c  (fast, but division must be exact)
- ``power(a, b, c)`` --  a = b^c, where 0^0 gives 1
- ``neg(a, b)``      --  a = -b
- ``abs(a, b)``      --  a = abs(b)
-


=== Error Conditions and Exceptions ===
%----------------------------------------------------------------------

Error conditions are signalled by exceptions.  Examples of error conditions
are impossible arithmetic operations such as division by zero, overly large
arguments (//e.g.// second argument to binomial must fit into a machine
``long``), and exhaustion of resources.

Currently the exception structure is very simplistic:
- exceptions indicating exhaustion of resources are those from the
    system, this library does not catch them;
- all other errors produce a ``CoCoA::ErrorInfo`` exception; for instance
 | ``ERR::ArgTooBig``   | value supplied is too large for the answer to be computed |
 | ``ERR::BadArg``      | unsuitable arg(s) supplied (or input number too large)    |
 | ``ERR::BadNumBase``  | the base must be between 2 and 36                         |
 | ``ERR::BadPwrZero``  | attempt to raise 0 to negative power                      |
 | ``ERR::DivByZero``   | division by zero                                          |
 | ``ERR::ExpTooBig``   | exponent is too large                                     |
 | ``ERR::IntDivByNeg`` | inexact integer division by a negative divisor            |
 | ``ERR::NegExp``      | negative exponent                                         |
 | ``ERR::ZeroModulus`` | the modulus specified is zero                             |


== Maintainer Documentation ==
%======================================================================

The implementation of ``cmp`` is more convoluted than I'd like; it must
avoid internal overflow.

The implementation of ``RoundDiv`` was more difficult than I had expected.
Part of the problem was making sure that needless overflow would never
occur: this was especially relevant in the auxiliary functions
``uround_half_up`` and ``uround_half_down``.  It would be nice if a
neater implementation could be achieved -- it seems strange that the
C/C++ standard libraries do not already offer such a function.  The
standard C functions ``lround`` almost achieves what is needed here, but
there are two significant shortcomings: rounding is always away from zero
(rather than towards +infinity), and there could be loss of accuracy if
the quotient exceeds 1/epsilon.  There is also a standard function ``ldiv``
which computes quotient and remainder, but it seems to be faster to compute
the two values explicitly.

NOTE: if you change rounding of halves, you must change TWO fns (``RoundDiv``
for machine ints and ``RoundDiv`` for big ints).


== Bugs, shortcomings and other ideas ==
%======================================================================

The power functions could allow high powers of -1,0,1 (without complaining about
the exponent being too big).  But is it worth it?

Only partial access to all the various division functions offered by the
C interface to GMP.  Many other GMP functions are not directly accessible.

``IsExactIroot`` has rather a lot of signatures.


== Main changes ==
%======================================================================

**2014**
- March
 - clarified that 0^0 gives 1

**2012**
- May (v0.9951):
 - moved common operations on [[BigInt]] and [[MachineInt]]
   together into ``IntOperations``
-


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% For "txt2tags safety" leave 2 empty lines after the last line of text.
