package jscl.math.polynomial;
import jscl.math.Generic;
import jscl.math.JsclBoolean;
import jscl.math.JsclInteger;
import javax.annotation.Nonnull;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;
class ArrayPolynomialBoolean extends ArrayPolynomialModular {
ArrayPolynomialBoolean(Monomial monomialFactory) {
super(monomialFactory, JsclBoolean.factory);
}
ArrayPolynomialBoolean(int size, Monomial monomialFactory) {
this(monomialFactory);
init(size);
}
void init(int size) {
monomial = new Monomial[size];
this.size = size;
}
void resize(int size) {
int length = monomial.length;
if (size < length) {
Monomial monomial[] = new Monomial[size];
System.arraycopy(this.monomial, length - size, monomial, 0, size);
this.monomial = monomial;
this.size = size;
}
}
@Nonnull
public Polynomial subtract(@Nonnull Polynomial that) {
if (that.signum() == 0) return this;
ArrayPolynomialBoolean q = (ArrayPolynomialBoolean) that;
ArrayPolynomialBoolean p = (ArrayPolynomialBoolean) 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) {
p.monomial[--i] = m1;
m1 = i1 > 0 ? monomial[--i1] : null;
} else if (c > 0) {
p.monomial[--i] = m2;
m2 = i2 > 0 ? q.monomial[--i2] : null;
} else {
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;
return subtract(polynomial);
}
public Polynomial multiplyAndSubtract(Monomial monomial, Generic generic, Polynomial polynomial) {
if (generic.signum() == 0) return this;
return multiplyAndSubtract(generic, polynomial.multiply(monomial));
}
public Polynomial multiply(Generic generic) {
if (generic.signum() == 0) return valueOf(JsclInteger.valueOf(0));
return this;
}
public Polynomial multiply(Monomial monomial) {
if (defined) {
Map map = new TreeMap(ordering);
for (int i = 0; i < size; i++) {
Monomial m = this.monomial[i].multiply(monomial);
if (map.containsKey(m)) map.remove(m);
else map.put(m, null);
}
ArrayPolynomialBoolean p = (ArrayPolynomialBoolean) newinstance(map.size());
Iterator it = map.keySet().iterator();
for (int i = 0; i < p.size; i++) p.monomial[i] = (Monomial) it.next();
p.degree = degree(p);
p.sugar = sugar + monomial.degree();
return p;
} else {
if (monomial.degree() == 0) return this;
ArrayPolynomialBoolean p = (ArrayPolynomialBoolean) newinstance(size);
for (int i = 0; i < size; i++) p.monomial[i] = this.monomial[i].multiply(monomial);
p.degree = degree + monomial.degree();
p.sugar = sugar + monomial.degree();
return p;
}
}
protected Generic getCoef(int n) {
return new JsclBoolean(1);
}
protected void setCoef(int n, Generic generic) {
}
protected ArrayPolynomialGeneric newinstance(int n) {
return new ArrayPolynomialBoolean(n, monomialFactory);
}
}