package jscl.math.polynomial; import jscl.math.Generic; import jscl.math.JsclInteger; import jscl.math.ModularInteger; import javax.annotation.Nonnull; class ArrayPolynomialModular extends ArrayPolynomialGeneric { final int modulo; int coef[]; ArrayPolynomialModular(Monomial monomialFactory, Generic coefFactory) { super(monomialFactory, coefFactory); modulo = ((ModularInteger) coefFactory).modulo(); } ArrayPolynomialModular(int size, Monomial monomialFactory, Generic coefFactory) { this(monomialFactory, coefFactory); init(size); } void init(int size) { monomial = new Monomial[size]; coef = new int[size]; this.size = size; } void resize(int size) { int length = monomial.length; if (size < length) { Monomial monomial[] = new Monomial[size]; int coef[] = new int[size]; System.arraycopy(this.monomial, length - size, monomial, 0, size); System.arraycopy(this.coef, length - size, coef, 0, size); this.monomial = monomial; this.coef = coef; this.size = size; } } @Nonnull public Polynomial subtract(@Nonnull Polynomial that) { if (that.signum() == 0) return this; ArrayPolynomialModular q = (ArrayPolynomialModular) that; ArrayPolynomialModular p = (ArrayPolynomialModular) newinstance(size + q.size); int i = p.size; int i1 = size; int i2 = q.size; Monomial m1 = i1 > 0 ? monomial[--i1] : null; Monomial m2 = i2 > 0 ? q.monomial[--i2] : null; while (m1 != null || m2 != null) { int c = m1 == null ? 1 : (m2 == null ? -1 : -ordering.compare(m1, m2)); if (c < 0) { int a = coef[i1]; --i; p.monomial[i] = m1; p.coef[i] = a; m1 = i1 > 0 ? monomial[--i1] : null; } else if (c > 0) { int a = (int) (((long) modulo - (long) q.coef[i2]) % modulo); --i; p.monomial[i] = m2; p.coef[i] = a; m2 = i2 > 0 ? q.monomial[--i2] : null; } else { int a = (int) (((long) coef[i1] + (long) modulo - (long) q.coef[i2]) % modulo); if (a != 0) { --i; p.monomial[i] = m1; p.coef[i] = a; } m1 = i1 > 0 ? monomial[--i1] : null; m2 = i2 > 0 ? q.monomial[--i2] : null; } } p.resize(p.size - i); p.degree = degree(p); p.sugar = Math.max(sugar, q.sugar); return p; } public Polynomial multiplyAndSubtract(Generic generic, Polynomial polynomial) { if (generic.signum() == 0) return this; int g = generic.integerValue().intValue(); if (g == 1) return subtract(polynomial); ArrayPolynomialModular q = (ArrayPolynomialModular) polynomial; ArrayPolynomialModular p = (ArrayPolynomialModular) newinstance(size + q.size); int i = p.size; int i1 = size; int i2 = q.size; Monomial m1 = i1 > 0 ? monomial[--i1] : null; Monomial m2 = i2 > 0 ? q.monomial[--i2] : null; while (m1 != null || m2 != null) { int c = m1 == null ? 1 : (m2 == null ? -1 : -ordering.compare(m1, m2)); if (c < 0) { int a = coef[i1]; --i; p.monomial[i] = m1; p.coef[i] = a; m1 = i1 > 0 ? monomial[--i1] : null; } else if (c > 0) { int a = (int) (((long) modulo - ((long) q.coef[i2] * (long) g) % modulo) % modulo); --i; p.monomial[i] = m2; p.coef[i] = a; m2 = i2 > 0 ? q.monomial[--i2] : null; } else { int a = (int) (((long) coef[i1] + (long) modulo - ((long) q.coef[i2] * (long) g) % modulo) % modulo); if (a != 0) { --i; p.monomial[i] = m1; p.coef[i] = a; } m1 = i1 > 0 ? monomial[--i1] : null; m2 = i2 > 0 ? q.monomial[--i2] : null; } } p.resize(p.size - i); p.degree = degree(p); p.sugar = Math.max(sugar, q.sugar); return p; } public Polynomial multiplyAndSubtract(Monomial monomial, Generic generic, Polynomial polynomial) { if (defined) throw new UnsupportedOperationException(); if (generic.signum() == 0) return this; if (monomial.degree() == 0) return multiplyAndSubtract(generic, polynomial); int g = generic.integerValue().intValue(); ArrayPolynomialModular q = (ArrayPolynomialModular) polynomial; ArrayPolynomialModular p = (ArrayPolynomialModular) newinstance(size + q.size); int i = p.size; int i1 = size; int i2 = q.size; Monomial m1 = i1 > 0 ? this.monomial[--i1] : null; Monomial m2 = i2 > 0 ? q.monomial[--i2].multiply(monomial) : null; while (m1 != null || m2 != null) { int c = m1 == null ? 1 : (m2 == null ? -1 : -ordering.compare(m1, m2)); if (c < 0) { int a = coef[i1]; --i; p.monomial[i] = m1; p.coef[i] = a; m1 = i1 > 0 ? this.monomial[--i1] : null; } else if (c > 0) { int a = (int) (((long) modulo - ((long) q.coef[i2] * (long) g) % modulo) % modulo); --i; p.monomial[i] = m2; p.coef[i] = a; m2 = i2 > 0 ? q.monomial[--i2].multiply(monomial) : null; } else { int a = (int) (((long) coef[i1] + (long) modulo - ((long) q.coef[i2] * (long) g) % modulo) % modulo); if (a != 0) { --i; p.monomial[i] = m1; p.coef[i] = a; } m1 = i1 > 0 ? this.monomial[--i1] : null; m2 = i2 > 0 ? q.monomial[--i2].multiply(monomial) : null; } } p.resize(p.size - i); p.degree = degree(p); p.sugar = Math.max(sugar, q.sugar + monomial.degree()); return p; } public Polynomial multiply(Generic generic) { if (generic.signum() == 0) return valueOf(JsclInteger.valueOf(0)); int g = generic.integerValue().intValue(); if (g == 1) return this; ArrayPolynomialModular p = (ArrayPolynomialModular) newinstance(size); for (int i = 0; i < size; i++) { p.monomial[i] = monomial[i]; p.coef[i] = (int) (((long) coef[i] * (long) g) % modulo); } p.degree = degree; p.sugar = sugar; return p; } public Polynomial multiply(Monomial monomial) { if (defined) throw new UnsupportedOperationException(); if (monomial.degree() == 0) return this; ArrayPolynomialModular p = (ArrayPolynomialModular) newinstance(size); for (int i = 0; i < size; i++) { p.monomial[i] = this.monomial[i].multiply(monomial); p.coef[i] = coef[i]; } p.degree = degree + monomial.degree(); p.sugar = sugar + monomial.degree(); return p; } protected Generic coefficient(Generic generic) { return coefFactory.valueOf(generic); } protected Generic getCoef(int n) { return new ModularInteger(coef[n], modulo); } protected void setCoef(int n, Generic generic) { coef[n] = generic.integerValue().intValue(); } protected ArrayPolynomialGeneric newinstance(int n) { return new ArrayPolynomialModular(n, monomialFactory, coefFactory); } }