BigIntegers.java
package church.math;

import java.math.BigInteger;

import static church.lang.operators.Relational.Ordering;
import static church.lang.operators.Streams.$$encode;
import static java.math.BigInteger.*;

@SuppressWarnings("unchecked")
public class BigIntegers {
    public static BigInteger bigInteger(long i) {
        return valueOf(i);
    }

    public static <T> $$encode<T, BigInteger> $encode($$encode<T, String> $L0) {
        return (stream, a) -> $L0.$encode(stream, a.toString());
    }

    public static boolean $equal(BigInteger a, BigInteger b) {
        return a.equals(b);
    }

    public static BigInteger additive_identity() {
        return ZERO;
    }

    public static BigInteger $sum(BigInteger a, BigInteger b) {
        return a.add(b);
    }

    public static BigInteger $neg(BigInteger a) {
        return a.negate();
    }

    public static BigInteger multiplicative_identity() {
        return ONE;
    }

    public static BigInteger $prd(BigInteger a, BigInteger b) {
        return a.multiply(b);
    }

    public static BigInteger $pow(BigInteger a, int n) {
        return a.pow(n);
    }

    public static <T> T divide(BigInteger a, BigInteger b, church.lang.Functions.Function1<BigInteger, church.lang.Functions.Function1<BigInteger, T>> f) {
        BigInteger[] qNr = a.divideAndRemainder(b);
        return f.of(qNr[0]).of(qNr[1]);
    }

    public static BigInteger quotient(BigInteger a, BigInteger b) {
        return a.divide(b);
    }

    public static BigInteger $rem(BigInteger a, BigInteger b) {
        return a.remainder(b);
    }

    public static Ordering compare(BigInteger a, BigInteger b) {
        int c = a.compareTo(b);
        return (c < 0) ? Ordering.LT : (c > 0) ? Ordering.GT : Ordering.EQ;
    }

}