Skip to content

Commit

Permalink
invert, flt64 invert, identity
Browse files Browse the repository at this point in the history
  • Loading branch information
kspalaiologos committed Mar 1, 2023
1 parent 5387204 commit a956e83
Show file tree
Hide file tree
Showing 9 changed files with 153 additions and 45 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,12 @@
import palaiologos.kamilalisp.runtime.math.bit.*;
import palaiologos.kamilalisp.runtime.math.cmp.*;
import palaiologos.kamilalisp.runtime.math.hyperbolic.*;
import palaiologos.kamilalisp.runtime.math.num.Det;
import palaiologos.kamilalisp.runtime.math.num.PLUDecomposition;
import palaiologos.kamilalisp.runtime.math.num.*;
import palaiologos.kamilalisp.runtime.math.prime.IsPrime;
import palaiologos.kamilalisp.runtime.math.prime.NextPrime;
import palaiologos.kamilalisp.runtime.math.prime.PrimeFactors;
import palaiologos.kamilalisp.runtime.math.prime.PrimeNo;
import palaiologos.kamilalisp.runtime.math.trig.*;
import palaiologos.kamilalisp.runtime.math.num.LUDecomposition;
import palaiologos.kamilalisp.runtime.math.num.Trace;
import palaiologos.kamilalisp.runtime.cas.MatrixTrace;
import palaiologos.kamilalisp.runtime.meta.*;
import palaiologos.kamilalisp.runtime.net.*;
Expand Down Expand Up @@ -256,6 +253,8 @@ public static void registerDefault(Environment env) {
env.setPrimitive("num:PLU", "⎕⍉↙↗", new Atom(new PLUDecomposition()));
env.setPrimitive("num:trace", "⎕∑", new Atom(new Trace()));
env.setPrimitive("num:det", "⎕∆", new Atom(new Det()));
env.setPrimitive("num:I", "⎕I", new Atom(new I()));
env.setPrimitive("num:invert", "⎕¯¹", new Atom(new Inv()));

env.setPrimitive("cas:matrix:trace", new Atom(new MatrixTrace()));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,7 @@ public void registerFlt64(Environment env) {
env.setPrimitive("flt64:LU", new Atom(new Flt64LU()));
env.setPrimitive("flt64:PLU", new Atom(new Flt64PLU()));
env.setPrimitive("flt64:det", new Atom(new Flt64Det()));
env.setPrimitive("flt64:invert", new Atom(new Flt64Inv()));
env.setPrimitive("flt64:trace", new Atom(new Flt64Trace()));
env.setPrimitive("flt64:e", toAtom(Math.E));
env.setPrimitive("flt64:pi", toAtom(Math.PI));
Expand Down
54 changes: 29 additions & 25 deletions src/main/java/palaiologos/kamilalisp/runtime/flt64/Flt64Det.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,41 +9,28 @@
import java.util.List;

public class Flt64Det extends PrimitiveFunction implements Lambda {
@Override
public Atom apply(Environment env, List<Atom> args) {
Atom a1 = args.get(0);
if (Rank.computeRank(a1) != 2) {
throw new RuntimeException("Expected a matrix of rank 2.");
}

List<List<Atom>> l1 = a1.getList().stream().map(Atom::getList).toList();
if (l1.stream().anyMatch(x -> x.size() != l1.get(0).size())) {
throw new RuntimeException("Expected a square matrix.");
}

double[][] A = l1.stream().map(x -> x.stream().mapToDouble(Flt64Base::toFlt64).toArray()).toArray(double[][]::new);

public static double det(double[][] A) {
if(A.length <= 1)
throw new RuntimeException("Expected at least a 2x2 matrix.");
else if(A.length == 2) {
// 2x2 determinant.
return Flt64Base.toAtom(A[0][0] * A[1][1] - A[0][1] * A[1][0]);
return A[0][0] * A[1][1] - A[0][1] * A[1][0];
} else if(A.length == 3) {
// 3x3 determinant.
return Flt64Base.toAtom(
return
A[0][0] * A[1][1] * A[2][2] +
A[0][1] * A[1][2] * A[2][0] +
A[0][2] * A[1][0] * A[2][1] -
A[0][2] * A[1][1] * A[2][0] -
A[0][1] * A[1][0] * A[2][2] -
A[0][0] * A[1][2] * A[2][1]
);
A[0][1] * A[1][2] * A[2][0] +
A[0][2] * A[1][0] * A[2][1] -
A[0][2] * A[1][1] * A[2][0] -
A[0][1] * A[1][0] * A[2][2] -
A[0][0] * A[1][2] * A[2][1]
;
} else {
double[][][] lup;
try {
lup = Flt64PLU.lu(A);
} catch(ArithmeticException e) {
return Atom.FALSE;
return 0;
}

double sumDiagP = 0;
Expand All @@ -56,12 +43,29 @@ else if(A.length == 2) {
prodU *= lup[1][i][i];

double detp = (lup[2].length - sumDiagP - 1) % 2 == 0 ? 1 : -1;
return Flt64Base.toAtom(detp * prodL * prodU);
return detp * prodL * prodU;
}
}

@Override
public Atom apply(Environment env, List<Atom> args) {
Atom a1 = args.get(0);
if (Rank.computeRank(a1) != 2) {
throw new RuntimeException("Expected a matrix of rank 2.");
}

List<List<Atom>> l1 = a1.getList().stream().map(Atom::getList).toList();
if (l1.stream().anyMatch(x -> x.size() != l1.get(0).size())) {
throw new RuntimeException("Expected a square matrix.");
}

double[][] A = l1.stream().map(x -> x.stream().mapToDouble(Flt64Base::toFlt64).toArray()).toArray(double[][]::new);

return Flt64Base.toAtom(det(A));
}

@Override
protected String name() {
return null;
return "flt64:det";
}
}
41 changes: 41 additions & 0 deletions src/main/java/palaiologos/kamilalisp/runtime/flt64/Flt64Inv.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package palaiologos.kamilalisp.runtime.flt64;

import palaiologos.kamilalisp.atom.Atom;
import palaiologos.kamilalisp.atom.Environment;
import palaiologos.kamilalisp.atom.Lambda;
import palaiologos.kamilalisp.atom.PrimitiveFunction;
import palaiologos.kamilalisp.runtime.array.Rank;

import java.util.Arrays;
import java.util.List;

public class Flt64Inv extends PrimitiveFunction implements Lambda {
@Override
public Atom apply(Environment env, List<Atom> args) {
Atom a1 = args.get(0);
if (Rank.computeRank(a1) != 2) {
throw new RuntimeException("Expected a matrix of rank 2.");
}

List<List<Atom>> l1 = a1.getList().stream().map(Atom::getList).toList();
if (l1.stream().anyMatch(x -> x.size() != l1.get(0).size())) {
throw new RuntimeException("Expected a square matrix.");
}

double[][] A = l1.stream().map(x -> x.stream().mapToDouble(Flt64Base::toFlt64).toArray()).toArray(double[][]::new);

double invdet = 1 / Flt64Det.det(A);
for(int i = 0; i < A.length; i++) {
for(int j = 0; j < A.length; j++) {
A[i][j] *= invdet;
}
}

return new Atom(Arrays.stream(A).map(x -> new Atom(Arrays.stream(x).mapToObj(Flt64Base::toAtom).toList())).toList());
}

@Override
protected String name() {
return "flt64:invert";
}
}
4 changes: 2 additions & 2 deletions src/main/java/palaiologos/kamilalisp/runtime/math/Slash.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
import java.util.stream.Collectors;

public class Slash extends PrimitiveFunction implements Lambda {
private static Atom quot2(Environment e, Atom a, Atom b) {
public static Atom quot2(Environment e, Atom a, Atom b) {
a.assertTypes(Type.INTEGER, Type.REAL, Type.COMPLEX, Type.STRING, Type.LIST);
b.assertTypes(Type.INTEGER, Type.REAL, Type.COMPLEX, Type.STRING, Type.LIST);
if (a.getType() == Type.COMPLEX && b.getType() == Type.COMPLEX) {
Expand Down Expand Up @@ -41,7 +41,7 @@ private static Atom quot2(Environment e, Atom a, Atom b) {
}
}

private static Atom quot1(Environment e, Atom a) {
public static Atom quot1(Environment e, Atom a) {
a.assertTypes(Type.INTEGER, Type.REAL, Type.COMPLEX, Type.LIST);
if (a.getType() == Type.COMPLEX) {
return new Atom(a.getComplex().reciprocal(e.getMathContext()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import java.util.stream.Collectors;

public class Star extends PrimitiveFunction implements Lambda {
private static Atom multiply2(Atom a, Atom b) {
public static Atom multiply2(Atom a, Atom b) {
a.assertTypes(Type.INTEGER, Type.REAL, Type.COMPLEX, Type.STRING, Type.LIST);
b.assertTypes(Type.INTEGER, Type.REAL, Type.COMPLEX, Type.STRING, Type.LIST);
if (a.getType() == Type.COMPLEX && b.getType() == Type.COMPLEX) {
Expand Down
31 changes: 18 additions & 13 deletions src/main/java/palaiologos/kamilalisp/runtime/math/num/Det.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,11 @@

import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.MathContext;
import java.util.List;

public class Det extends PrimitiveFunction implements Lambda {
@Override
public Atom apply(Environment env, List<Atom> args) {
Atom a1 = args.get(0);
if (Rank.computeRank(a1) != 2) {
throw new RuntimeException("Expected a matrix of rank 2.");
}

List<List<Atom>> l1 = a1.getList().stream().map(Atom::getList).toList();
public static Atom det(MathContext mc, List<List<Atom>> l1) {
if (l1.stream().anyMatch(x -> x.size() != l1.get(0).size())) {
throw new RuntimeException("Expected a square matrix.");
}
Expand Down Expand Up @@ -48,7 +42,7 @@ public Atom apply(Environment env, List<Atom> args) {
BigDecimal[][] A = l1.stream().map(x -> x.stream().map(Atom::getReal).toArray(BigDecimal[]::new)).toArray(BigDecimal[][]::new);
BigDecimal[][][] lup;
try {
lup = PLUDecomposition.lu(env.getMathContext(), A);
lup = PLUDecomposition.lu(mc, A);
} catch (ArithmeticException e) {
return Atom.FALSE;
}
Expand All @@ -63,7 +57,7 @@ public Atom apply(Environment env, List<Atom> args) {

BigDecimal detp = BigInteger.valueOf(lup[2].length - 1).subtract(sumDiagP).remainder(BigInteger.TWO).compareTo(BigInteger.ZERO) == 0 ? BigDecimal.ONE : BigDecimal.ONE.negate();
BigDecimal result = detp.multiply(prodL).multiply(prodU);
result = result.setScale(env.getMathContext().getPrecision(), env.getMathContext().getRoundingMode());
result = result.setScale(mc.getPrecision(), mc.getRoundingMode());
return new Atom(result);
}
} else {
Expand Down Expand Up @@ -93,7 +87,7 @@ public Atom apply(Environment env, List<Atom> args) {
BigComplex[][] A = l1.stream().map(x -> x.stream().map(Atom::getComplex).toArray(BigComplex[]::new)).toArray(BigComplex[][]::new);
BigComplex[][][] lup;
try {
lup = PLUDecomposition.lu(env.getMathContext(), A);
lup = PLUDecomposition.lu(mc, A);
} catch (ArithmeticException e) {
return Atom.FALSE;
}
Expand All @@ -108,13 +102,24 @@ public Atom apply(Environment env, List<Atom> args) {

BigComplex detp = BigInteger.valueOf(lup[2].length - 1).subtract(sumDiagP).remainder(BigInteger.TWO).compareTo(BigInteger.ZERO) == 0 ? BigComplex.ONE : BigComplex.ONE.negate();
BigComplex result = detp.multiply(prodL).multiply(prodU);
BigDecimal re = result.re.setScale(env.getMathContext().getPrecision(), env.getMathContext().getRoundingMode());
BigDecimal im = result.im.setScale(env.getMathContext().getPrecision(), env.getMathContext().getRoundingMode());
BigDecimal re = result.re.setScale(mc.getPrecision(), mc.getRoundingMode());
BigDecimal im = result.im.setScale(mc.getPrecision(), mc.getRoundingMode());
return new Atom(BigComplex.valueOf(re, im));
}
}
}

@Override
public Atom apply(Environment env, List<Atom> args) {
Atom a1 = args.get(0);
if (Rank.computeRank(a1) != 2) {
throw new RuntimeException("Expected a matrix of rank 2.");
}

List<List<Atom>> l1 = a1.getList().stream().map(Atom::getList).toList();
return det(env.getMathContext(), l1);
}

@Override
protected String name() {
return "num:det";
Expand Down
31 changes: 31 additions & 0 deletions src/main/java/palaiologos/kamilalisp/runtime/math/num/I.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package palaiologos.kamilalisp.runtime.math.num;

import palaiologos.kamilalisp.atom.Atom;
import palaiologos.kamilalisp.atom.Environment;
import palaiologos.kamilalisp.atom.Lambda;
import palaiologos.kamilalisp.atom.PrimitiveFunction;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;

public class I extends PrimitiveFunction implements Lambda {
@Override
public Atom apply(Environment env, List<Atom> args) {
assertArity(args, 1);
int size = args.get(0).getInteger().intValueExact();
List<Atom> result = new ArrayList<>();
for(int i = 0; i < size; i++) {
List<Atom> row = new ArrayList<>();
for(int j = 0; j < size; j++)
row.add(new Atom(BigInteger.valueOf(i == j ? 1 : 0)));
result.add(new Atom(row));
}
return new Atom(result);
}

@Override
protected String name() {
return "num:I";
}
}
27 changes: 27 additions & 0 deletions src/main/java/palaiologos/kamilalisp/runtime/math/num/Inv.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package palaiologos.kamilalisp.runtime.math.num;

import palaiologos.kamilalisp.atom.*;
import palaiologos.kamilalisp.runtime.array.Rank;
import palaiologos.kamilalisp.runtime.math.Slash;
import palaiologos.kamilalisp.runtime.math.Star;

import java.util.List;

public class Inv extends PrimitiveFunction implements Lambda {
@Override
public Atom apply(Environment env, List<Atom> args) {
Atom a1 = args.get(0);
if (Rank.computeRank(a1) != 2) {
throw new RuntimeException("Expected a matrix of rank 2.");
}

List<List<Atom>> l1 = a1.getList().stream().map(Atom::getList).toList();
Atom result = Det.det(env.getMathContext(), l1);
return Star.multiply2(Slash.quot1(env, result), a1);
}

@Override
protected String name() {
return "num:invert";
}
}

0 comments on commit a956e83

Please sign in to comment.