package de.skuzzle.polly.tools.math; /** * Predefines several useful fields for usage with a matrix. Please note that the set * of Integers does not form a valid field as not every item has a valid multiplicative * inverse. * * @author Simon * */ public class Fields { /** * Defines a {@link Field} over the residue class set of integers modulo 5. */ public final static Field<Integer> INT_MOD_5 = integerModulo(5); /** * Defines a {@link Field} over the residue class set of integers modulo 7. */ public final static Field<Integer> INT_MOD_7 = integerModulo(7); /** * Defines a {@link Field} over the set of Doubles. */ public final static Field<Double> DOUBLE = new Field<Double>() { @Override public Double multiply(Double left, Double right) { return left * right; } @Override public Double getMultiplicativeNeutral() { return 1.0; } @Override public Double getMultiplicativeInverse(Double element) { return 1.0 / element; } @Override public Double getAdditiveNeutral() { return 0.0; } @Override public Double getAdditiveInverse(Double element) { return -element; } @Override public Double add(Double left, Double right) { return left + right; } }; private static Integer[] extendedEuklid(Integer a, Integer b) { if (b == 0) { return new Integer[] {a, 1, 0}; } Integer[] tmp = extendedEuklid(b, a % b); return new Integer[] {tmp[0], tmp[2], (tmp[1] - (a/b) * tmp[2]) }; } /** * Creates a {@link Field} over the residue class of integers modulo p. Please note * that in order for the result to be a valid field, p must be a prime number. * Otherwise, there won't exist a valid multiplicative inverse for each element. * * @param p A prime number of which the residue classes are calculated. * @return A {@link Field} over the residue class modulo p. */ public static Field<Integer> integerModulo(final int p) { return new Field<Integer>() { @Override public Integer getAdditiveNeutral() { return 0; } @Override public Integer getAdditiveInverse(Integer element) { return p - element; } @Override public Integer add(Integer left, Integer right) { return Math.abs(left + right) % p; } @Override public Integer getMultiplicativeNeutral() { return 1; } @Override public Integer getMultiplicativeInverse(Integer element) { Integer[] e = extendedEuklid(element, p); Integer k = e[1]; if (k < 0) { return p + k; } else { return k; } } @Override public Integer multiply(Integer left, Integer right) { int r = (left * right) % p; if (r < 0) { r = p + r; } return r; } }; } private Fields() {}; }