diff --git a/mihxil-algebra/src/main/java/org/meeuw/math/abstractalgebra/dim2/FieldMatrix2.java b/mihxil-algebra/src/main/java/org/meeuw/math/abstractalgebra/dim2/FieldMatrix2.java new file mode 100644 index 00000000..a96a2eee --- /dev/null +++ b/mihxil-algebra/src/main/java/org/meeuw/math/abstractalgebra/dim2/FieldMatrix2.java @@ -0,0 +1,227 @@ +/* + * Copyright 2022 Michiel Meeuwissen + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.meeuw.math.abstractalgebra.dim2; + +import java.lang.reflect.Array; +import java.util.Arrays; +import java.util.stream.Collectors; + +import org.meeuw.math.Equivalence; +import org.meeuw.math.WithScalarOperations; +import org.meeuw.math.abstractalgebra.*; +import org.meeuw.math.exceptions.InvalidElementCreationException; +import org.meeuw.math.exceptions.ReciprocalException; +import org.meeuw.math.validation.Square; + +/** + * @author Michiel Meeuwissen + * @since 0.4 + */ +public class FieldMatrix2> + implements MultiplicativeGroupElement>, + WithScalarOperations, E> +{ + + @Square(2) + final E[][] values; + + final ScalarField elementStructure; + + final E zero; + + public static > FieldMatrix2 of( + E v00, E v01, + E v10, E v11) { + return of(v00.getStructure().getElementClass(), + v00, v01, + v10, v11); + + } + + + @SuppressWarnings("unchecked") + static > FieldMatrix2 of( + Class clazz, + E v00, E v01, + E v10, E v11 + ) { + E[][] fs = (E[][]) Array.newInstance(clazz, 3, 3); + fs[0][0] = v00; + fs[0][1] = v01; + + fs[1][0] = v10; + fs[1][1] = v11; + FieldMatrix2 fm = new FieldMatrix2<>(fs); + if (fm.determinant().isZero()) { + throw new InvalidElementCreationException("Determinant is zero, so this is not invertiable " + fm); + } + return fm; + + } + + public FieldMatrix2(@Square(3) E[][] values) { + this.elementStructure = values[0][0].getStructure(); + this.values = values; + this.zero = this.elementStructure.zero(); + } + + @Override + public FieldMatrix2 times(FieldMatrix2 multiplier) { + return new FieldMatrix2<>(timesMatrix(multiplier.values)); + } + + @Override + public FieldMatrix2 times(E multiplier) { + E[][] result = empty(); + for (int i = 0; i < 2; i++) { + for (int j = 0; j < 2; j++) { + result[i][j] = values[i][j].times(multiplier); + } + } + return new FieldMatrix2<>(result); + } + + @Override + public FieldMatrix2 dividedBy(E divisor) { + return times(divisor.reciprocal()); + } + + @SuppressWarnings({"unchecked"}) + public FieldVector2[] asVectors() { + FieldVector2[] result = (FieldVector2[]) new FieldVector2[2]; + result[0] = FieldVector2.of(values[0][0], values[0][1]); + result[1] = FieldVector2.of(values[1][0], values[1][1]); + return result; + } + + @Override + // https://www.mathsisfun.com/algebra/matrix-inverse-minors-cofactors-adjugate.html + public FieldMatrix2 reciprocal() throws ReciprocalException { + try { + E det = determinant(); + if (det.isZero()) { + throw new ReciprocalException("Determinant of " + this + " is zero"); + } + + return adjugate().dividedBy(det); + } catch (InvalidElementCreationException invalidElementCreationException) { + throw new ReciprocalException(invalidElementCreationException); + } + } + + public FieldMatrix2 adjugate() { + return new FieldMatrix2<>(adjugateMatrix()); + } + + E[][] adjugateMatrix() { + final E[][] adjugate = empty(); + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 3; j++) { + adjugate[j][i] = determinant2x2( + values[skip(0, i)][skip(0, j)], values[skip(0, i)][skip(1, j)], + values[skip(1, i)][skip(0, j)], values[skip(1, i)][skip(1, j)] + ); + if ((i + j) % 2 == 1) { + adjugate[j][i] = adjugate[j][i].negation(); + } + } + } + return adjugate; + } + private int skip(int i, int skip) { + return i < skip ? i : i + 1; + } +/* + + private E[][] transposedMatrix() { + final E[][] transpose = empty(); + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 3; j++) { + transpose[i][j] = values[j][i]; + } + } + return transpose; + } +*/ + + @SuppressWarnings("unchecked") + private E[][] empty() { + return (E[][]) Array.newInstance(elementStructure.getElementClass(), 2, 2); + } + + @Override + public FieldMatrix2Group getStructure() { + return FieldMatrix2Group.of(elementStructure); + } + + E[][] timesMatrix(@Square(2) E[][] matrix2) { + E[][] result = empty(); + for (int i = 0; i < 2; i++) { + for (int j = 0; j < 2; j++) { + E v = elementStructure.zero(); + for (int k = 0; k < 2; k++) { + v = v.plus(values[i][k].times(matrix2[k][j])); + } + result[i][j] = v; + } + } + return result; + } + + public E determinant() { + E a = values[0][0]; + E b = values[0][1]; + E c = values[1][0]; + E d = values[1][1]; + return a.times(d) + .minus( + b.times(c)); + + } + + E determinant2x2(E a, E b, E c, E d) { + return a.times(d).minus(b.times(c)); + } + + + + @Override + public String toString() { + return "(" + Arrays.stream(asVectors()).map(FieldVector2::toString).collect(Collectors.joining(", ")) + ")"; + } + + @SuppressWarnings("unchecked") + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + FieldMatrix2 that = (FieldMatrix2) o; + Equivalence equivalence = elementStructure.getEquivalence(); + boolean result = true; + for (int i = 0; i < 2; i++) { + for (int j = 0; j < 2; j++) { + result &= equivalence.test(values[i][j], that.values[i][j]); + } + } + return result; + } + + @Override + public int hashCode() { + return 0; + } +} diff --git a/mihxil-algebra/src/main/java/org/meeuw/math/abstractalgebra/dim2/FieldMatrix2Group.java b/mihxil-algebra/src/main/java/org/meeuw/math/abstractalgebra/dim2/FieldMatrix2Group.java new file mode 100644 index 00000000..e2946560 --- /dev/null +++ b/mihxil-algebra/src/main/java/org/meeuw/math/abstractalgebra/dim2/FieldMatrix2Group.java @@ -0,0 +1,70 @@ +/* + * Copyright 2022 Michiel Meeuwissen + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.meeuw.math.abstractalgebra.dim2; + +import lombok.Getter; + +import java.util.HashMap; +import java.util.Map; + +import org.meeuw.math.abstractalgebra.*; + +/** + * A square 3x3 matrix of any {@link ScalarFieldElement ScalarFieldElements}. + * + * @author Michiel Meeuwissen + * @since 0.4 + */ +public class FieldMatrix2Group> + extends AbstractAlgebraicStructure> + implements MultiplicativeGroup> { + + + public static final Map, FieldMatrix2Group> INSTANCES = new HashMap<>(); + + @Getter + private final ScalarField elementStructure; + + private final FieldMatrix2 one; + + @SuppressWarnings("unchecked") + public static > FieldMatrix2Group of(ScalarField elementStructure) { + return (FieldMatrix2Group) INSTANCES.computeIfAbsent(elementStructure, FieldMatrix2Group::new); + } + + @SuppressWarnings({"unchecked", "rawtypes"}) + private FieldMatrix2Group(ScalarField elementStructure) { + super((Class) FieldMatrix2.class); + this.elementStructure = elementStructure; + E eOne = elementStructure.one(); + E eZero = elementStructure.zero(); + one = FieldMatrix2.of( + elementStructure.getElementClass(), + eOne, eZero, + eZero, eOne); + } + + @Override + public FieldMatrix2 one() { + return one; + } + + @Override + public Cardinality getCardinality() { + return Cardinality.C; //elementStructure.getCardinality(); + } + +} diff --git a/mihxil-algebra/src/main/java/org/meeuw/math/abstractalgebra/dim2/FieldVector2.java b/mihxil-algebra/src/main/java/org/meeuw/math/abstractalgebra/dim2/FieldVector2.java new file mode 100644 index 00000000..7e73e214 --- /dev/null +++ b/mihxil-algebra/src/main/java/org/meeuw/math/abstractalgebra/dim2/FieldVector2.java @@ -0,0 +1,181 @@ +/* + * Copyright 2022 Michiel Meeuwissen + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.meeuw.math.abstractalgebra.dim2; + +import lombok.With; + +import java.math.BigDecimal; +import java.util.Arrays; +import java.util.Iterator; + +import org.meeuw.math.NonAlgebraic; +import org.meeuw.math.WithScalarOperations; +import org.meeuw.math.abstractalgebra.*; +import org.meeuw.math.abstractalgebra.reals.BigDecimalElement; +import org.meeuw.math.abstractalgebra.reals.RealNumber; +import org.meeuw.math.exceptions.FieldIncompleteException; +import org.meeuw.math.numbers.Sizeable; + +import static java.math.BigDecimal.ZERO; + +/** + * A 3-dimension vector on a {@link CompleteField}. + * + * @author Michiel Meeuwissen + */ +public class FieldVector2> + implements + Sizeable, + Vector, E>, + WithScalarOperations, E> { + + @With + final E x; + @With + final E y; + + + public static > FieldVector2 of(E x, E y) { + return new FieldVector2<>(x, y); + } + + public static FieldVector2 of(double x, double y) { + return new FieldVector2<>(RealNumber.of(x), RealNumber.of(y)); + } + + public static FieldVector2 of(BigDecimal x, BigDecimal y) { + return of(new BigDecimalElement(x, ZERO), new BigDecimalElement(y, ZERO)); + } + + public FieldVector2(E x, E y) { + this.x = x; + this.y = y; + } + + public FieldVector2 times(FieldMatrix2 matrix2) { + return of( + matrix2.values[0][0].times(x).plus(matrix2.values[0][1].times(y)), + matrix2.values[1][0].times(x).plus(matrix2.values[1][1].times(y)) + ); + } + + /* public FieldVector3 times(double multiplier) { + + return of(x.times(multiplier), y.times(multiplier), z.times(multiplier)); + }*/ + + + @Override + @NonAlgebraic + public E abs() { + E result = (x.sqr().plus(y.sqr())); + if (result instanceof CompleteFieldElement) { + return (E) ((CompleteFieldElement) result).sqrt(); + } else { + throw new FieldIncompleteException("Field of " + this + " is not complete"); + } + } + + @Override + public FieldVector2 times(E multiplier) { + return of(x.times(multiplier), y.times(multiplier)); + } + + @Override + public FieldVector2 plus(FieldVector2 summand) { + return of( + x.plus(summand.x), + y.plus(summand.y) + ); + } + + @Override + public E dot(FieldVector2 multiplier) { + return (x.times(multiplier.x)).plus(y.times(multiplier.y)); + } + + @Override + public FieldVector2 negation() { + return of(x.negation(), y.negation()); + } + + @Override + public E get(int i) { + switch(i) { + case 0: return x; + case 1: return y; + default: throw new ArrayIndexOutOfBoundsException(); + } + } + + @Override + public VectorSpace> getSpace() { + return FieldVector2Space.of(x.getStructure()); + } + + @Override + public FieldVector2 dividedBy(E divisor) { + return new FieldVector2<>(x.dividedBy(divisor), y.dividedBy(divisor)); + } + + @Override + @lombok.NonNull + public Iterator iterator() { + return Arrays.asList(x, y).iterator(); + } + + @SuppressWarnings("rawtypes") + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + FieldVector2 vector3 = (FieldVector2) o; + + return x.equals(vector3.x) && + y.equals(vector3.y); + } + + @Override + public boolean eq(FieldVector2 o) { + if (this == o) return true; + + return x.eq(o.x) && + y.eq(o.y); + } + + @Override + public int hashCode() { + int result = x.hashCode(); + result = 31 * result + y.hashCode(); + return result; + } + + @Override + public String toString() { + return "(" + x + "," + y + ")"; + } + + @Override + public AbelianRing> getStructure() { + return getSpace(); + } + + @Override + public FieldVector2 times(FieldVector2 multiplier) { + return new FieldVector2<>(x.times(multiplier.x), y.times(multiplier.y)); + } +} diff --git a/mihxil-algebra/src/main/java/org/meeuw/math/abstractalgebra/dim2/FieldVector2Space.java b/mihxil-algebra/src/main/java/org/meeuw/math/abstractalgebra/dim2/FieldVector2Space.java new file mode 100644 index 00000000..d72b736c --- /dev/null +++ b/mihxil-algebra/src/main/java/org/meeuw/math/abstractalgebra/dim2/FieldVector2Space.java @@ -0,0 +1,86 @@ +/* + * Copyright 2022 Michiel Meeuwissen + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.meeuw.math.abstractalgebra.dim2; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.meeuw.math.abstractalgebra.*; + +/** + * @author Michiel Meeuwissen + */ +public class FieldVector2Space> + implements VectorSpace> { + + private static final Map, FieldVector2Space> INSTANCES = new ConcurrentHashMap<>(); + + final ScalarField scalarField; + + public FieldVector2Space(ScalarField scalarField) { + this.scalarField = scalarField; + } + + @SuppressWarnings("unchecked") + public static > FieldVector2Space of(ScalarField field) { + return (FieldVector2Space) INSTANCES.computeIfAbsent(field, k -> new FieldVector2Space<>(field)); + } + + @Override + public int getDimension() { + return 3; + } + + @Override + public FieldVector2 zero() { + return FieldVector2.of(scalarField.zero(), scalarField.zero()); + } + + @Override + public ScalarField getField() { + return scalarField; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + FieldVector2Space that = (FieldVector2Space) o; + + return scalarField.equals(that.scalarField); + } + + @Override + public int hashCode() { + return scalarField.hashCode(); + } + + @Override + public FieldVector2 one() { + return FieldVector2.of(scalarField.one(), scalarField.one()); + } + + @Override + public Cardinality getCardinality() { + return scalarField.getCardinality(); + } + + @Override + public Class> getElementClass() { + return (Class>) zero().getClass(); + } +}