BigDecimals.java
package com.acme.math;

import java.math.BigDecimal;

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

@SuppressWarnings("unchecked")
public class BigDecimals {
    public static BigDecimal bigDecimal(double d) {
        return valueOf(d);
    }

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

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

    public static BigDecimal additive_identity() {
        return ZERO;
    }

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

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

    public static BigDecimal multiplicative_identity() {
        return ONE;
    }

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

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

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

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

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

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

}