GaussianInteger.java
package com.acme.math;

import church.math.Complex;

import static church.lang.operators.Arithmetic.*;
import static church.math.Complex.complex;

@SuppressWarnings("unchecked")
public class GaussianInteger {
    public static interface $Round2<T> {
        public T round2(T a, T b);
    }

    public static <T> $Round2<T> round2($Quotient<T> $L0, $$sum<T> $L1, $$prd<T, T> $L2, $Sign<T> $L3, $Multiplicative_identity<T> $L4) {
        return (a, b) -> $L0.quotient($L1.$sum(a, $L0.quotient($L2.$prd($L3.sign(a), b), $L1.$sum($L4.multiplicative_identity(), $L4.multiplicative_identity()))), b);
    }

    public static interface $ComplexQuotient<T, U> {
        public Complex<U> complexQuotient(Complex<T> $0, Complex<U> $1);
    }

    public static <T, U> $ComplexQuotient<T, U> complexQuotient($$sum<U> $L0, $$prd<T, U> $L1, $$sub<U> $L2, $$prd<U, U> $L3, $Round2<U> $L4) {
        return ($0, $1) -> {
            U na  = $L0.$sum($L1.$prd($0.a, $1.a), $L1.$prd($0.b, $1.b));
            U nb  = $L2.$sub($L1.$prd($0.b, $1.a), $L1.$prd($0.a, $1.b));
            U den = $L0.$sum($L3.$prd($1.a, $1.a), $L3.$prd($1.b, $1.b));
            return complex($L4.round2(na, den), $L4.round2(nb, den));
        };
    }

    public static <T> $$rem<Complex<T>> $rem($$sub<Complex<T>> $L0, $$prd<Complex<T>, Complex<T>> $L1, $ComplexQuotient<T, T> $L2) {
        return (n, d) -> $L0.$sub(n, $L1.$prd(d, $L2.complexQuotient(n, d)));
    }

}