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).
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 kth 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
=
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.
==
, !=
<
, <=
, >
, >=
 comparison (using the normal arithmetic ordering)
 see also the cmp
function below.
++
, 
(prefix, e.g. ++a
) use these if you can
++
, 
(postfix, e.g. a++
) avoid these if you can, as they create temporaries
(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.
(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 nonnegative 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 nonnegative 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).
Only for BigInt
mantissa(N)
 N
represented as a floatingpoint 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.
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)
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 = bc
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 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:
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 
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).
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.
2014
BigInt
and MachineInt
together into IntOperations
