------------------------------------------------------------------------------ --- A collection of common operations on integer numbers. --- Most operations make no assumption on the precision of integers. --- Operation bitNot is necessarily an exception. --- --- @author Sergio Antoy --- @version Sept 4, 2003 -- Thu Sep 4 12:42:05 PDT 2003 ------------------------------------------------------------------------------ module Integer(pow, ilog, isqrt, factorial, binomial, abs, max, min, max3, min3, maxlist, minlist, bitTrunc, bitAnd, bitOr, bitNot, bitXor, even, odd) where ------------------------------------------------------------------ -- Public Operations ------------------------------------------------------------------ --- The value of pow a b is a --- raised to the power of b. --- Fails if b < 0. --- Executes in O(log b) steps. --- --- @param a - The base. --- @param b - The exponent. --- @return a raised to the power of b. pow a b | b>= 0 = powaux 1 a b where powaux n x y = if y == 0 then n else powaux (n * if (y `mod` 2 == 1) then x else 1) (x * x) (y `div` 2) --- The value of ilog n is the floor of the logarithm --- in the base 10 of n. --- Fails if n <= 0. --- For positive integers, the returned value is --- 1 less the number of digits in the decimal representation of n. --- --- @param n - The argument. --- @return the floor of the logarithm in the base 10 of n. ilog n | n>0 = if n<10 then 0 else 1 + ilog (n `div` 10) --- The value of isqrt n is the floor --- of the square root of n. --- Fails if n < 0. --- Executes in O(log n) steps, but there must be a better way. --- --- @param n - The argument. --- @return the floor of the square root of n. isqrt n | n >= 0 = if n == 0 then 0 else if n < 4 then 1 else aux 2 n where aux low past = -- invariant low <= result < past if past == low+1 then low else let cand = (past + low) `div` 2 in if cand*cand > n then aux low cand else aux cand past --- The value of factorial n is the factorial of n. --- Fails if n < 0. --- --- @param n - The argument. --- @return the factorial of n. factorial n | n >= 0 = if n == 0 then 1 else n * factorial (n-1) --- The value of binomial n m is --- n*(n-1)*...*(n-m+1)/m*(m-1)*...1 --- Fails if m <= 0 or n < m. --- --- @param n - Argument. --- @param m - Argument. --- @return the binomial coefficient of n over m. binomial n m | m > 0 && n >= m = aux m n `div` factorial m where aux x y = if x == 0 then 1 else y * aux (x-1) (y-1) --- The value of abs n is the absolute value of n. --- --- @param n - The argument. --- @return the absolute value of n. abs n = if n<0 then -n else n --- Returns the maximum of the two arguments --- --- @param n - Argument. --- @param m - Argument. --- @return the maximum of n and m. max n m = if nn and m. min n m = if nn, m and p. max3 n m p = max n (max m p) --- Returns the minimum of the three arguments. --- --- @param n - Argument. --- @param m - Argument. --- @param p - Argument. --- @return the minimum among n, m and p. min3 n m p = min n (min m p) --- Returns the maximum of a list of integer values. --- Fails if the list is empty. --- --- @param l - The list of values. --- @return the maximum element of l. maxlist [n] = n maxlist (n:m:ns) = max n (maxlist (m:ns)) --- Returns the minimum of a list of integer values. --- Fails if the list is empty. --- --- @param l - The list of values. --- @return the minimum element of l. minlist [n] = n minlist (n:m:ns) = min n (minlist (m:ns)) --- The value of bitTrunc n m is the value of the n --- least significant bits of m. --- --- @param n - Argument. --- @param m - Argument. --- @return m truncated to the n least significant bits. bitTrunc n m = bitAnd (pow 2 n - 1) m --- Returns the bitwise AND of the two arguments. --- --- @param n - Argument. --- @param m - Argument. --- @return the bitwise and of n and m. bitAnd n m = if m == 0 then 0 else let p = 2 * bitAnd (n `div` 2) (m `div` 2) q = if m `mod` 2 == 0 then 0 else n `mod` 2 in p + q --- Returns the bitwise inclusive OR of the two arguments. --- --- @param n - Argument. --- @param m - Argument. --- @return the bitwise inclusive or of n and m. bitOr n m = if m == 0 then n else let p = 2 * bitOr (n `div` 2) (m `div` 2) q = if m `mod` 2 == 1 then 1 else n `mod` 2 in p + q --- Returns the bitwise NOT of the argument. --- Since integers have unlimited precision, --- only the 32 least significant bits are computed. --- --- @param n - Argument. --- @return the bitwise negation of n truncated to 32 bits. bitNot n = aux 32 n where aux c m = if c==0 then 0 else let p = 2 * aux (c-1) (m `div` 2) q = 1 - m `mod` 2 in p + q --- Returns the bitwise exclusive OR of the two arguments. --- --- @param n - Argument. --- @param m - Argument. --- @return the bitwise exclusive of n and m. bitXor n m = if m == 0 then n else let p = 2 * bitXor (n `div` 2) (m `div` 2) q = if m `mod` 2 == n `mod` 2 then 0 else 1 in p + q --- Returns whether an integer is even --- --- @param n - Argument. --- @return whether n is even. even n = n `mod` 2 == 0 --- Returns whether an integer is odd --- --- @param n - Argument. --- @return whether n is odd. odd n = n `mod` 2 /= 0