diff --git a/common/src/main/java/dk/jonaslindstrom/ruffini/common/algorithms/ChineseRemainderTheorem.java b/common/src/main/java/dk/jonaslindstrom/ruffini/common/algorithms/ChineseRemainderTheorem.java index 8e47b636..a7eea01e 100644 --- a/common/src/main/java/dk/jonaslindstrom/ruffini/common/algorithms/ChineseRemainderTheorem.java +++ b/common/src/main/java/dk/jonaslindstrom/ruffini/common/algorithms/ChineseRemainderTheorem.java @@ -24,7 +24,7 @@ public E apply(Vector a, Vector m) { return a.get(0); } - EuclideanAlgorithm.Result bezout = euclideanAlgorithm.gcd(m.get(0), m.get(1)); + EuclideanAlgorithm.Result bezout = euclideanAlgorithm.applyExtended(m.get(0), m.get(1)); Calculator c = new Calculator<>(domain); diff --git a/common/src/main/java/dk/jonaslindstrom/ruffini/common/algorithms/EuclideanAlgorithm.java b/common/src/main/java/dk/jonaslindstrom/ruffini/common/algorithms/EuclideanAlgorithm.java index 83422a49..9d228f25 100644 --- a/common/src/main/java/dk/jonaslindstrom/ruffini/common/algorithms/EuclideanAlgorithm.java +++ b/common/src/main/java/dk/jonaslindstrom/ruffini/common/algorithms/EuclideanAlgorithm.java @@ -15,13 +15,35 @@ public EuclideanAlgorithm(EuclideanDomain domain) { this.ring = domain; } + public E apply(E a, E b) { + if (ring.isZero(b)) { + return a; + } + return apply(b, ring.mod(a, b)); + } + + public E apply(List inputs) { + if (inputs == null || inputs.isEmpty()) { + throw new IllegalArgumentException("Empty input list"); + } + + if (inputs.size() == 1) { + return inputs.get(0); + } + return apply(inputs.get(0), apply(inputs.subList(1, inputs.size()))); + } + + public E apply(E... inputs) { + return apply(List.of(inputs)); + } + /** * Calculate the greatest common divisor d of a and b, and the coefficients * x,y of the Bezout identity ax + by = d . * * @return The triple (d, x, y). */ - public Result gcd(E a, E b) { + public Result applyExtended(E a, E b) { E s_1 = ring.zero(); E s_0 = ring.identity(); E t_1 = ring.identity(); @@ -47,19 +69,19 @@ public Result gcd(E a, E b) { return new Result<>(r_0, s_0, t_0); } - public ExtendedResult gcd(List inputs) { + public ExtendedResult applyExtended(List inputs) { if (inputs.size() == 1) { return new ExtendedResult<>(inputs.get(0), List.of(this.ring.identity())); } - ExtendedResult recursion = gcd(inputs.subList(1, inputs.size())); - Result result = gcd(inputs.get(0), recursion.gcd); + ExtendedResult recursion = applyExtended(inputs.subList(1, inputs.size())); + Result result = applyExtended(inputs.get(0), recursion.gcd); LinkedList bezoutCoefficients = recursion.bezout.stream().map(bPrime -> ring.multiply(bPrime, result.y())).collect(Collectors.toCollection(LinkedList::new)); bezoutCoefficients.addFirst(result.x()); return new ExtendedResult<>(result.gcd, bezoutCoefficients); } - public ExtendedResult gcd(E... inputs) { - return gcd(List.of(inputs)); + public ExtendedResult applyExtended(E... inputs) { + return applyExtended(List.of(inputs)); } public record Result(E gcd, E x, E y) { diff --git a/common/src/main/java/dk/jonaslindstrom/ruffini/common/matrices/algorithms/GramSchmidtOverRing.java b/common/src/main/java/dk/jonaslindstrom/ruffini/common/matrices/algorithms/GramSchmidtOverRing.java index 80051e39..59682200 100644 --- a/common/src/main/java/dk/jonaslindstrom/ruffini/common/matrices/algorithms/GramSchmidtOverRing.java +++ b/common/src/main/java/dk/jonaslindstrom/ruffini/common/matrices/algorithms/GramSchmidtOverRing.java @@ -31,7 +31,7 @@ private Vector sub(Vector v, Vector u) { } private E gcd(E a, E b) { - return euclideanAlgorithm.gcd(a, b).gcd(); + return euclideanAlgorithm.applyExtended(a, b).gcd(); } private Vector normalize(Vector v) { diff --git a/common/src/main/java/dk/jonaslindstrom/ruffini/common/structures/FieldOfFractions.java b/common/src/main/java/dk/jonaslindstrom/ruffini/common/structures/FieldOfFractions.java index fbf057ab..24af4e4a 100644 --- a/common/src/main/java/dk/jonaslindstrom/ruffini/common/structures/FieldOfFractions.java +++ b/common/src/main/java/dk/jonaslindstrom/ruffini/common/structures/FieldOfFractions.java @@ -16,7 +16,7 @@ public FieldOfFractions(EuclideanDomain ring) { } public Fraction reduce(E n, E d) { - E gcd = euclideanAlgorithm.gcd(n, d).gcd(); + E gcd = euclideanAlgorithm.applyExtended(n, d).gcd(); return new Fraction<>(baseRing.divide(n, gcd).getFirst(), baseRing.divide(d, gcd).getFirst()); } diff --git a/common/src/test/java/AlgorithmsTests.java b/common/src/test/java/AlgorithmsTests.java index 131436ca..43a3cee8 100644 --- a/common/src/test/java/AlgorithmsTests.java +++ b/common/src/test/java/AlgorithmsTests.java @@ -127,7 +127,7 @@ public void testEuclideanAlgorithm() { for (int i = 0; i < tests; i++) { BigInteger a = new BigInteger(16, random); BigInteger b = new BigInteger(16, random); - EuclideanAlgorithm.Result gcd = new EuclideanAlgorithm<>(integers).gcd(a, b); + EuclideanAlgorithm.Result gcd = new EuclideanAlgorithm<>(integers).applyExtended(a, b); Assert.assertEquals(a.gcd(b), gcd.gcd()); Assert.assertEquals(gcd.gcd(), gcd.x().multiply(a).add(gcd.y().multiply(b))); } @@ -136,7 +136,7 @@ public void testEuclideanAlgorithm() { BigInteger a = new BigInteger(16, random); BigInteger b = new BigInteger(16, random); BigInteger c = new BigInteger(16, random); - EuclideanAlgorithm.ExtendedResult gcd = new EuclideanAlgorithm<>(integers).gcd(a, b, c); + EuclideanAlgorithm.ExtendedResult gcd = new EuclideanAlgorithm<>(integers).applyExtended(a, b, c); Assert.assertEquals(a.gcd(b).gcd(c), gcd.gcd()); Assert.assertEquals(gcd.gcd(), gcd.bezout().get(0).multiply(a).add(gcd.bezout().get(1).multiply(b)).add(gcd.bezout().get(2).multiply(c))); } diff --git a/finite-fields/src/main/java/dk/jonaslindstrom/ruffini/finitefields/AlgebraicFieldExtension.java b/finite-fields/src/main/java/dk/jonaslindstrom/ruffini/finitefields/AlgebraicFieldExtension.java index 014c5b75..f585359f 100644 --- a/finite-fields/src/main/java/dk/jonaslindstrom/ruffini/finitefields/AlgebraicFieldExtension.java +++ b/finite-fields/src/main/java/dk/jonaslindstrom/ruffini/finitefields/AlgebraicFieldExtension.java @@ -22,7 +22,7 @@ public AlgebraicFieldExtension(F field, String element, Polynomial minimalPol @Override public Polynomial invert(Polynomial a) { EuclideanAlgorithm.Result> r = - new EuclideanAlgorithm<>((PolynomialRing) super.ring).gcd(a, super.mod); + new EuclideanAlgorithm<>((PolynomialRing) super.ring).applyExtended(a, super.mod); assert (r.gcd().degree() == 0); return r.x().scale(field.invert(r.gcd().getCoefficient(0)), field); } diff --git a/finite-fields/src/main/java/dk/jonaslindstrom/ruffini/finitefields/BigFiniteField.java b/finite-fields/src/main/java/dk/jonaslindstrom/ruffini/finitefields/BigFiniteField.java index 61413d56..44f9485d 100644 --- a/finite-fields/src/main/java/dk/jonaslindstrom/ruffini/finitefields/BigFiniteField.java +++ b/finite-fields/src/main/java/dk/jonaslindstrom/ruffini/finitefields/BigFiniteField.java @@ -30,7 +30,7 @@ public BigFiniteField(BigPrimeField baseField, Polynomial mod) { @Override public Polynomial invert(Polynomial a) { return new EuclideanAlgorithm<>((PolynomialRing) super.ring) - .gcd(a, mod).x(); + .applyExtended(a, mod).x(); } @Override diff --git a/finite-fields/src/main/java/dk/jonaslindstrom/ruffini/finitefields/BigPrimeField.java b/finite-fields/src/main/java/dk/jonaslindstrom/ruffini/finitefields/BigPrimeField.java index 4d12f357..b2d525ad 100644 --- a/finite-fields/src/main/java/dk/jonaslindstrom/ruffini/finitefields/BigPrimeField.java +++ b/finite-fields/src/main/java/dk/jonaslindstrom/ruffini/finitefields/BigPrimeField.java @@ -17,7 +17,7 @@ public BigPrimeField(BigInteger p) { @Override public BigInteger invert(BigInteger a) { EuclideanAlgorithm.Result xgcd = - new EuclideanAlgorithm<>(BigIntegers.getInstance()).gcd(a, super.getModulus()); + new EuclideanAlgorithm<>(BigIntegers.getInstance()).applyExtended(a, super.getModulus()); if (!xgcd.gcd().equals(BigInteger.ONE)) { throw new NotInvertibleException(a); } diff --git a/finite-fields/src/main/java/dk/jonaslindstrom/ruffini/finitefields/FiniteField.java b/finite-fields/src/main/java/dk/jonaslindstrom/ruffini/finitefields/FiniteField.java index 7306cbe9..ad3e4a3f 100644 --- a/finite-fields/src/main/java/dk/jonaslindstrom/ruffini/finitefields/FiniteField.java +++ b/finite-fields/src/main/java/dk/jonaslindstrom/ruffini/finitefields/FiniteField.java @@ -98,7 +98,7 @@ public Polynomial element(Integer... coefficients) { @Override public Polynomial invert(Polynomial a) { return new EuclideanAlgorithm<>((PolynomialRing) super.ring) - .gcd(a, mod).x(); + .applyExtended(a, mod).x(); } @Override diff --git a/finite-fields/src/main/java/dk/jonaslindstrom/ruffini/finitefields/PrimeField.java b/finite-fields/src/main/java/dk/jonaslindstrom/ruffini/finitefields/PrimeField.java index 2ef76552..fa735159 100644 --- a/finite-fields/src/main/java/dk/jonaslindstrom/ruffini/finitefields/PrimeField.java +++ b/finite-fields/src/main/java/dk/jonaslindstrom/ruffini/finitefields/PrimeField.java @@ -16,7 +16,7 @@ public PrimeField(Integer p) { @Override public Integer invert(Integer a) { EuclideanAlgorithm.Result gcd = new EuclideanAlgorithm<>(Integers.getInstance()) - .gcd(a, super.mod); + .applyExtended(a, super.mod); if (gcd.gcd() != 1) { throw new NotInvertibleException(super.mod); } diff --git a/finite-fields/src/main/java/dk/jonaslindstrom/ruffini/finitefields/algorithms/BerlekampRabinAlgorithm.java b/finite-fields/src/main/java/dk/jonaslindstrom/ruffini/finitefields/algorithms/BerlekampRabinAlgorithm.java index f2c536e6..810ee310 100644 --- a/finite-fields/src/main/java/dk/jonaslindstrom/ruffini/finitefields/algorithms/BerlekampRabinAlgorithm.java +++ b/finite-fields/src/main/java/dk/jonaslindstrom/ruffini/finitefields/algorithms/BerlekampRabinAlgorithm.java @@ -76,7 +76,7 @@ public Integer apply(Polynomial f) { š”½ā‚šx.subtract(gā‚–, š”½ā‚šx.identity())); for (Polynomial candidate : candidates) { - Polynomial g = gcd.gcd(fā‚–, candidate).gcd(); + Polynomial g = gcd.applyExtended(fā‚–, candidate).gcd(); if (g.degree() > 0) { return š”½ā‚š.subtract(apply(g), k); } diff --git a/finite-fields/src/main/java/dk/jonaslindstrom/ruffini/finitefields/quadraticform/ClassGroup.java b/finite-fields/src/main/java/dk/jonaslindstrom/ruffini/finitefields/quadraticform/ClassGroup.java index 9e47d143..c0992a0f 100644 --- a/finite-fields/src/main/java/dk/jonaslindstrom/ruffini/finitefields/quadraticform/ClassGroup.java +++ b/finite-fields/src/main/java/dk/jonaslindstrom/ruffini/finitefields/quadraticform/ClassGroup.java @@ -6,7 +6,7 @@ import java.math.BigInteger; /** - * This implements the ideal class group for a negative discrimant. + * This implements the ideal class group for a negative discriminant. */ public class ClassGroup implements Group> { diff --git a/finite-fields/src/main/java/dk/jonaslindstrom/ruffini/finitefields/quadraticform/QuadraticForm.java b/finite-fields/src/main/java/dk/jonaslindstrom/ruffini/finitefields/quadraticform/QuadraticForm.java index 68382313..33bfae2e 100644 --- a/finite-fields/src/main/java/dk/jonaslindstrom/ruffini/finitefields/quadraticform/QuadraticForm.java +++ b/finite-fields/src/main/java/dk/jonaslindstrom/ruffini/finitefields/quadraticform/QuadraticForm.java @@ -112,9 +112,7 @@ public QuadraticForm compose(QuadraticForm other) { E a1 = this.a; E a2 = other.a; - E b1 = this.b; E b2 = other.b; - E c1 = this.c; E c2 = other.c; if (ordering.compare(a1, a2) > 0) { @@ -126,9 +124,9 @@ public QuadraticForm compose(QuadraticForm other) { throw new IllegalArgumentException("Discriminants must be equal."); } - EuclideanAlgorithm euclideanAlgorithm = new EuclideanAlgorithm<>(ring); + EuclideanAlgorithm gcd = new EuclideanAlgorithm<>(ring); - E s = ring.divideExact(ring.add(b1, b2), 2); + E s = ring.divideExact(ring.add(this.b, b2), 2); E n = ring.subtract(b2, s); E d, y1; @@ -136,7 +134,7 @@ public QuadraticForm compose(QuadraticForm other) { d = a1; y1 = ring.zero(); } else { - EuclideanAlgorithm.Result duv = euclideanAlgorithm.gcd(a1, a2); + EuclideanAlgorithm.Result duv = gcd.applyExtended(a1, a2); d = duv.gcd(); y1 = duv.y(); } @@ -147,13 +145,13 @@ public QuadraticForm compose(QuadraticForm other) { y2 = ring.negate(ring.identity()); d1 = d; } else { - EuclideanAlgorithm.Result duv = euclideanAlgorithm.gcd(s, d); + EuclideanAlgorithm.Result duv = gcd.applyExtended(s, d); d1 = duv.gcd(); x2 = duv.x(); y2 = ring.negate(duv.y()); } - E g = euclideanAlgorithm.gcd(d1, c1, c2, ring.abs(n, ordering)).gcd(); + E g = gcd.applyExtended(d1, this.c, c2, ring.abs(n, ordering)).gcd(); E v1 = ring.divideExact(ring.multiply(g, a1), d1); E v2 = ring.divideExact(a2, d1); E r = ring.subtract(ring.multiply(y1, y2, n), ring.mod(ring.multiply(x2, c2), v1)); diff --git a/integers/src/main/java/dk/jonaslindstrom/ruffini/integers/algorithms/CongruenceSolver.java b/integers/src/main/java/dk/jonaslindstrom/ruffini/integers/algorithms/CongruenceSolver.java index a0830b0e..d3d86fa5 100644 --- a/integers/src/main/java/dk/jonaslindstrom/ruffini/integers/algorithms/CongruenceSolver.java +++ b/integers/src/main/java/dk/jonaslindstrom/ruffini/integers/algorithms/CongruenceSolver.java @@ -29,7 +29,7 @@ public BigInteger solve(List p, List q) { List inputs = new ArrayList<>(); inputs.add(m); inputs.addAll(p); - EuclideanAlgorithm.ExtendedResult xgcd = euclideanAlgorithm.gcd(inputs); + EuclideanAlgorithm.ExtendedResult xgcd = euclideanAlgorithm.applyExtended(inputs); if (!xgcd.gcd().equals(BigInteger.ONE)) { throw new IllegalArgumentException("m and p_1, ..., p_r are not pairwise co-prime."); }