VectorExample.java
package com.acme.vectors;

import church.lang.Array;
import church.lang.Array.$CreateArray;
import church.lang.Array.$WriteElementsToStream;
import church.lang.Array.$WriteEmbracedElementsToStream;
import church.lang.ByteStream;
import church.lang.Collections.$Size;
import church.lang.JavaClasses.$Java_class;
import church.lang.operators.Arithmetic;
import church.lang.operators.Arithmetic.*;
import church.lang.operators.Relational;
import church.lang.operators.Relational.$$equal;
import church.lang.operators.Relational.$$lt;
import church.lang.operators.Relational.$$neq;
import church.lang.operators.Streams.$$encode;
import church.math.Fraction;
import church.math.Fraction.$Canonical;
import church.math.Vector;
import church.math.Vector.*;
import church.primitives.Doubles;
import church.primitives.Integers;
import church.primitives.Objects;

import static church.lang.operators.Streams.output;
import static church.math.Fraction.fraction;
import static church.math.Vector.*;

@SuppressWarnings("unchecked")
public class VectorExample {
    private static final $Java_class<Integer>                                                                  $S0   = () -> Integer.class;
    private static final $CreateArray<Integer>                                                                 $S1   = Array.createArray($S0);
    private static final $CreateVector<Integer>                                                                $S2   = Vector.createVector($S1);
    private static final $Size<Vector<Integer>>                                                                $S3   = Vector::size;
    private static final $$neg<Integer>                                                                        $S4   = Integers::$neg;
    private static final $$neg<Vector<Integer>>                                                                $S5   = Vector.$neg($S2, $S3, $S4);
    private static final $$sum<Integer>                                                                        $S6   = Integers::$sum;
    private static final $$sum<Vector<Integer>>                                                                $S7   = Vector.$sum($S2, $S3, $S6);
    private static final $$sub<Vector<Integer>>                                                                $S8   = Arithmetic.$sub($S7, $S5);
    private static final $$encode<ByteStream, String>                                                          $S9   = Objects::$encode;
    private static final $$encode<ByteStream, Integer>                                                         $S10  = Integers::$encode;
    private static final $WriteElementsToStream<ByteStream, Integer>                                           $S11  = Array.writeElementsToStream($S10, $S9);
    private static final $WriteEmbracedElementsToStream<ByteStream, Integer, String, String>                   $S12  = Array.writeEmbracedElementsToStream($S9, $S11, $S9);
    private static final $$encode<ByteStream, Vector<Integer>>                                                 $S13  = Vector.$encode($S12);
    private static final $$equal<Integer>                                                                      $S14  = Integers::$equal;
    private static final $$equal<Integer[]>                                                                    $S15  = Array.$equal($S14);
    private static final $$equal<Vector<Integer>>                                                              $S16  = Vector.$equal($S15);
    private static final $Java_class<Vector<Integer>>                                                          $S17  = () -> (Class<Vector<Integer>>) (Object) Vector.class;
    private static final $CreateArray<Vector<Integer>>                                                         $S18  = Array.createArray($S17);
    private static final $CreateVector<Vector<Integer>>                                                        $S19  = Vector.createVector($S18);
    private static final $Size<Vector<Vector<Integer>>>                                                        $S20  = Vector::size;
    private static final $$sum<Vector<Vector<Integer>>>                                                        $S21  = Vector.$sum($S19, $S20, $S7);
    private static final $$neg<Vector<Vector<Integer>>>                                                        $S22  = Vector.$neg($S19, $S20, $S5);
    private static final $$sub<Vector<Vector<Integer>>>                                                        $S23  = Arithmetic.$sub($S21, $S22);
    private static final $WriteElementsToStream<ByteStream, Vector<Integer>>                                   $S24  = Array.writeElementsToStream($S13, $S9);
    private static final $WriteEmbracedElementsToStream<ByteStream, Vector<Integer>, String, String>           $S25  = Array.writeEmbracedElementsToStream($S9, $S24, $S9);
    private static final $$encode<ByteStream, Vector<Vector<Integer>>>                                         $S26  = Vector.$encode($S25);
    private static final $$equal<Vector<Integer>[]>                                                            $S27  = Array.$equal($S16);
    private static final $$equal<Vector<Vector<Integer>>>                                                      $S28  = Vector.$equal($S27);
    private static final $Additive_identity<Integer>                                                           $S29  = Integers::additive_identity;
    private static final $Sum1<Integer>                                                                        $S30  = Vector.sum1($S29, $S6);
    private static final $$prd<Integer, Integer>                                                               $S31  = Integers::$prd;
    private static final $$prd<Vector<Vector<Integer>>, Vector<Vector<Integer>>>                               $S32  = Vector.$prd($S19, $S20, $S2, $S3, $S30, $S3, $S31);
    private static final $Size<Vector<Vector<Double>>>                                                         $S33  = Vector::size;
    private static final $$equal<Double>                                                                       $S34  = Doubles::$equal;
    private static final $$neq<Double>                                                                         $S35  = Relational.$neq($S34);
    private static final $Additive_identity<Double>                                                            $S36  = Doubles::additive_identity;
    private static final $Pivot<Double>                                                                        $S37  = Vector.pivot($S33, $S35, $S36);
    private static final $Java_class<Vector<Double>>                                                           $S38  = () -> (Class<Vector<Double>>) (Object) Vector.class;
    private static final $CreateArray<Vector<Double>>                                                          $S39  = Array.createArray($S38);
    private static final $CreateVector<Vector<Double>>                                                         $S40  = Vector.createVector($S39);
    private static final $Java_class<Double>                                                                   $S41  = () -> Double.class;
    private static final $CreateArray<Double>                                                                  $S42  = Array.createArray($S41);
    private static final $CreateVector<Double>                                                                 $S43  = Vector.createVector($S42);
    private static final $Size<Vector<Double>>                                                                 $S44  = Vector::size;
    private static final $$div<Double, Double>                                                                 $S45  = Doubles::$div;
    private static final $$sub<Double>                                                                         $S46  = Doubles::$sub;
    private static final $$prd<Double, Double>                                                                 $S47  = Doubles::$prd;
    private static final $GaussJordanStep<Double>                                                              $S48  = Vector.gaussJordanStep($S37, $S40, $S33, $S43, $S44, $S45, $S46, $S47);
    private static final $GaussJordanElimination<Double>                                                       $S49  = Vector.gaussJordanElimination($S33, $S48);
    private static final $CreateMatrix<Double>                                                                 $S50  = Vector.createMatrix($S40, $S43);
    private static final $Multiplicative_identity<Double>                                                      $S51  = Doubles::multiplicative_identity;
    private static final $MultiplicativeIdentityMatrix<Double>                                                 $S52  = Vector.multiplicativeIdentityMatrix($S50, $S51, $S36);
    private static final $$rcp<Vector<Vector<Double>>>                                                         $S53  = Vector.$rcp($S49, $S52, $S33);
    private static final $$encode<ByteStream, Double>                                                          $S54  = Doubles::$encode;
    private static final $WriteElementsToStream<ByteStream, Double>                                            $S55  = Array.writeElementsToStream($S54, $S9);
    private static final $WriteEmbracedElementsToStream<ByteStream, Double, String, String>                    $S56  = Array.writeEmbracedElementsToStream($S9, $S55, $S9);
    private static final $$encode<ByteStream, Vector<Double>>                                                  $S57  = Vector.$encode($S56);
    private static final $WriteElementsToStream<ByteStream, Vector<Double>>                                    $S58  = Array.writeElementsToStream($S57, $S9);
    private static final $WriteEmbracedElementsToStream<ByteStream, Vector<Double>, String, String>            $S59  = Array.writeEmbracedElementsToStream($S9, $S58, $S9);
    private static final $$encode<ByteStream, Vector<Vector<Double>>>                                          $S60  = Vector.$encode($S59);
    private static final $$equal<Double[]>                                                                     $S61  = Array.$equal($S34);
    private static final $$equal<Vector<Double>>                                                               $S62  = Vector.$equal($S61);
    private static final $$equal<Vector<Double>[]>                                                             $S63  = Array.$equal($S62);
    private static final $$equal<Vector<Vector<Double>>>                                                       $S64  = Vector.$equal($S63);
    private static final $Java_class<Vector<Fraction<Integer>>>                                                $S65  = () -> (Class<Vector<Fraction<Integer>>>) (Object) Vector.class;
    private static final $CreateArray<Vector<Fraction<Integer>>>                                               $S66  = Array.createArray($S65);
    private static final $CreateVector<Vector<Fraction<Integer>>>                                              $S67  = Vector.createVector($S66);
    private static final $Java_class<Fraction<Integer>>                                                        $S68  = () -> (Class<Fraction<Integer>>) (Object) Fraction.class;
    private static final $CreateArray<Fraction<Integer>>                                                       $S69  = Array.createArray($S68);
    private static final $CreateVector<Fraction<Integer>>                                                      $S70  = Vector.createVector($S69);
    private static final $CreateMatrix<Fraction<Integer>>                                                      $S71  = Vector.createMatrix($S67, $S70);
    private static final $Multiplicative_identity<Integer>                                                     $S72  = Integers::multiplicative_identity;
    private static final $$encode<ByteStream, Fraction<Integer>>                                               $S73  = Fraction.$encode($S14, $S72, $S10, $S9);
    private static final $WriteElementsToStream<ByteStream, Fraction<Integer>>                                 $S74  = Array.writeElementsToStream($S73, $S9);
    private static final $WriteEmbracedElementsToStream<ByteStream, Fraction<Integer>, String, String>         $S75  = Array.writeEmbracedElementsToStream($S9, $S74, $S9);
    private static final $$encode<ByteStream, Vector<Fraction<Integer>>>                                       $S76  = Vector.$encode($S75);
    private static final $WriteElementsToStream<ByteStream, Vector<Fraction<Integer>>>                         $S77  = Array.writeElementsToStream($S76, $S9);
    private static final $WriteEmbracedElementsToStream<ByteStream, Vector<Fraction<Integer>>, String, String> $S78  = Array.writeEmbracedElementsToStream($S9, $S77, $S9);
    private static final $$encode<ByteStream, Vector<Vector<Fraction<Integer>>>>                               $S79  = Vector.$encode($S78);
    private static final $Size<Vector<Vector<Fraction<Integer>>>>                                              $S80  = Vector::size;
    private static final $$equal<Fraction<Integer>>                                                            $S81  = Fraction.$equal($S14);
    private static final $$neq<Fraction<Integer>>                                                              $S82  = Relational.$neq($S81);
    private static final $Additive_identity<Fraction<Integer>>                                                 $S83  = Fraction.additive_identity($S29, $S72);
    private static final $Pivot<Fraction<Integer>>                                                             $S84  = Vector.pivot($S80, $S82, $S83);
    private static final $Size<Vector<Fraction<Integer>>>                                                      $S85  = Vector::size;
    private static final $Sign<Integer>                                                                        $S86  = Integers::sign;
    private static final $Gcd<Integer>                                                                         $S87  = Integers::gcd;
    private static final $$dof<Integer>                                                                        $S88  = Integers::$dof;
    private static final $Canonical<Integer>                                                                   $S89  = Fraction.canonical($S31, $S86, $S87, $S88);
    private static final $$prd<Fraction<Integer>, Fraction<Integer>>                                           $S90  = Fraction.$prd($S89, $S31);
    private static final $$lt<Integer>                                                                         $S91  = Integers::$lt;
    private static final $$rcp<Fraction<Integer>>                                                              $S92  = Fraction.$rcp($S91, $S29, $S4);
    private static final $$div<Fraction<Integer>, Fraction<Integer>>                                           $S93  = Arithmetic.$div($S90, $S92);
    private static final $$sum<Fraction<Integer>>                                                              $S94  = Fraction.$sum($S89, $S6, $S31);
    private static final $$neg<Fraction<Integer>>                                                              $S95  = Fraction.$neg($S4);
    private static final $$sub<Fraction<Integer>>                                                              $S96  = Arithmetic.$sub($S94, $S95);
    private static final $GaussJordanStep<Fraction<Integer>>                                                   $S97  = Vector.gaussJordanStep($S84, $S67, $S80, $S70, $S85, $S93, $S96, $S90);
    private static final $GaussJordanElimination<Fraction<Integer>>                                            $S98  = Vector.gaussJordanElimination($S80, $S97);
    private static final $Multiplicative_identity<Fraction<Integer>>                                           $S99  = Fraction.multiplicative_identity($S72);
    private static final $MultiplicativeIdentityMatrix<Fraction<Integer>>                                      $S100 = Vector.multiplicativeIdentityMatrix($S71, $S99, $S83);
    private static final $$rcp<Vector<Vector<Fraction<Integer>>>>                                              $S101 = Vector.$rcp($S98, $S100, $S80);
    private static final $Sum1<Fraction<Integer>>                                                              $S102 = Vector.sum1($S83, $S94);
    private static final $$prd<Vector<Vector<Fraction<Integer>>>, Vector<Vector<Fraction<Integer>>>>           $S103 = Vector.$prd($S67, $S80, $S70, $S85, $S102, $S85, $S90);
    private static final $$equal<Fraction<Integer>[]>                                                          $S104 = Array.$equal($S81);
    private static final $$equal<Vector<Fraction<Integer>>>                                                    $S105 = Vector.$equal($S104);
    private static final $$equal<Vector<Fraction<Integer>>[]>                                                  $S106 = Array.$equal($S105);
    private static final $$equal<Vector<Vector<Fraction<Integer>>>>                                            $S107 = Vector.$equal($S106);
    private static final $$neq<Integer>                                                                        $S108 = Relational.$neq($S14);
    private static final $Pivot<Integer>                                                                       $S109 = Vector.pivot($S20, $S108, $S29);
    private static final $$sub<Integer>                                                                        $S110 = Integers::$sub;
    private static final $BareissStep<Integer>                                                                 $S111 = Vector.bareissStep($S109, $S72, $S19, $S20, $S2, $S3, $S88, $S110, $S31);
    private static final $BareissElimination<Integer, Vector<Vector<Integer>>>                                 $S112 = Vector.bareissElimination($S20, $S111);
    private static final $CreateMatrix<Integer>                                                                $S113 = Vector.createMatrix($S19, $S2);
    private static final $MultiplicativeIdentityMatrix<Integer>                                                $S114 = Vector.multiplicativeIdentityMatrix($S113, $S72, $S29);
    private static final $Cofactors<Integer>                                                                   $S115 = Vector.cofactors($S112, $S114, $S20);
    private static final $BareissElimination<Integer, Integer>                                                 $S116 = Vector.bareissElimination($S20, $S111);
    private static final $Determinant<Integer>                                                                 $S117 = Vector.determinant($S116, $S20, $S114);

    public static void main(String[] args) {
        Vector<Integer> v1 = vector(1, 2);
        Vector<Integer> v2 = vector(3, 4);
        Vector<Integer> v3 = $S5.$neg(v1);
        Vector<Integer> v4 = $S8.$sub(v2, v1);
        $S9.$encode($S13.$encode($S9.$encode(output, "v4 = "), v4), "\n");
        assert $S16.$equal(v4, vector(2, 2));
        Vector<Vector<Integer>> m1 = vector(vector(1, 2), vector(3, 4));
        Vector<Vector<Integer>> m2 = vector(vector(4, 3), vector(2, 1));
        Vector<Vector<Integer>> m3 = $S23.$sub(m2, m1);
        $S9.$encode($S26.$encode($S9.$encode(output, "m3 = "), m3), "\n");
        assert $S28.$equal(m3, vector(vector(3, 1), vector(-1, -3)));
        Vector<Vector<Integer>> m4 = $S32.$prd(m1, m2);
        $S9.$encode($S26.$encode($S9.$encode(output, "m4 = "), m4), "\n");
        assert $S28.$equal(m4, vector(vector(8, 5), vector(20, 13)));
        Vector<Vector<Double>> m5 = vector(vector(1.0, 2.0), vector(3.0, 4.0));
        Vector<Vector<Double>> m6 = $S53.$rcp(m5);
        $S9.$encode($S60.$encode($S9.$encode(output, "m6 = "), m6), "\n");
        assert $S64.$equal(m6, vector(vector(-2.0, 1.0), vector(1.5, -0.5)));
        Vector<Vector<Integer>>           a7 = vector(vector(1, 2), vector(3, 4));
        Vector<Vector<Fraction<Integer>>> m7 = $S71.createMatrix(2, 2, i -> j -> fraction(get(get(a7, i), j), 1));
        $S9.$encode($S79.$encode($S9.$encode(output, "m7 = "), m7), "\n");
        Vector<Vector<Fraction<Integer>>> m8 = $S101.$rcp(m7);
        $S9.$encode($S79.$encode($S9.$encode(output, "m8 = "), m8), "\n");
        Vector<Vector<Fraction<Integer>>> m9 = $S103.$prd(m7, m8);
        $S9.$encode($S79.$encode($S9.$encode(output, "m9 = "), m9), "\n");
        Vector<Vector<Fraction<Integer>>> I = $S100.multiplicativeIdentityMatrix(2);
        assert $S107.$equal(m9, I);
        Vector<Vector<Integer>> m10 = vector(vector(0, 1, 2), vector(1, 2, 5), vector(2, 5, 8));
        Vector<Vector<Integer>> m11 = $S115.cofactors(m10);
        $S9.$encode($S26.$encode($S9.$encode(output, "m11 = "), m11), "\n");
        Vector<Vector<Integer>> m12 = $S32.$prd(m10, m11);
        $S9.$encode($S26.$encode($S9.$encode(output, "m12 = "), m12), "\n");
        int det = $S117.determinant(m10);
        $S9.$encode($S10.$encode($S9.$encode(output, "det = "), det), "\n");
        assert det == -4;
    }

}