All Downloads are FREE. Search and download functionalities are using the official Maven repository.

jscl.math.polynomial.ArrayPolynomial Maven / Gradle / Ivy

There is a newer version: 1.0.11
Show newest version
package jscl.math.polynomial;

import jscl.math.Expression;
import jscl.math.Generic;
import jscl.math.JsclInteger;
import jscl.math.Literal;

import javax.annotation.Nonnull;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;

final class ArrayPolynomial extends Polynomial {
	Term content[];
	int size;
	int degree;

	ArrayPolynomial(Monomial monomialFactory, Generic coefFactory) {
		super(monomialFactory, coefFactory);
	}

	ArrayPolynomial(int size, Monomial monomialFactory, Generic coefFactory) {
		this(monomialFactory, coefFactory);
		init(size);
	}

	public int size() {
		return size;
	}

	void init(int size) {
		content = new Term[size];
		this.size = size;
	}

	void resize(int size) {
		int length = content.length;
		if (size < length) {
			Term content[] = new Term[size];
			System.arraycopy(this.content, length - size, content, 0, size);
			this.content = content;
			this.size = size;
		}
	}

	public Iterator iterator(boolean direction, Monomial current) {
		return new ContentIterator(direction, current);
	}

	class ContentIterator implements Iterator {
		final boolean direction;
		int index;

		ContentIterator(boolean direction, Monomial current) {
			this.direction = direction;
			index = indexOf(current, direction);
		}

		public boolean hasNext() {
			return direction ? index > 0 : index < size;
		}

		public Object next() {
			return direction ? content[--index] : content[index++];
		}

		public void remove() {
			throw new UnsupportedOperationException();
		}
	}

	int indexOf(Monomial monomial, boolean direction) {
		if (monomial == null) return direction ? size : 0;
		int n = Arrays.binarySearch(content, new Term(monomial, null));
		return n < 0 ? -n - 1 : direction ? n : n + 1;
	}

	@Nonnull
	public Polynomial subtract(@Nonnull Polynomial that) {
		if (that.signum() == 0) return this;
		ArrayPolynomial q = (ArrayPolynomial) that;
		ArrayPolynomial p = newinstance(size + q.size);
		int i = p.size;
		int i1 = size;
		int i2 = q.size;
		Term t1 = i1 > 0 ? content[--i1] : null;
		Term t2 = i2 > 0 ? q.content[--i2] : null;
		while (t1 != null || t2 != null) {
			int c = t1 == null ? 1 : (t2 == null ? -1 : -ordering.compare(t1.monomial(), t2.monomial()));
			if (c < 0) {
				p.content[--i] = t1;
				t1 = i1 > 0 ? content[--i1] : null;
			} else if (c > 0) {
				p.content[--i] = t2.negate();
				t2 = i2 > 0 ? q.content[--i2] : null;
			} else {
				Term t = t1.subtract(t2);
				if (t.signum() != 0) p.content[--i] = t;
				t1 = i1 > 0 ? content[--i1] : null;
				t2 = i2 > 0 ? q.content[--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;
		if (generic.compareTo(JsclInteger.valueOf(1)) == 0) return subtract(polynomial);
		ArrayPolynomial q = (ArrayPolynomial) polynomial;
		ArrayPolynomial p = newinstance(size + q.size);
		int i = p.size;
		int i1 = size;
		int i2 = q.size;
		Term t1 = i1 > 0 ? content[--i1] : null;
		Term t2 = i2 > 0 ? q.content[--i2].multiply(generic) : null;
		while (t1 != null || t2 != null) {
			int c = t1 == null ? 1 : (t2 == null ? -1 : -ordering.compare(t1.monomial(), t2.monomial()));
			if (c < 0) {
				p.content[--i] = t1;
				t1 = i1 > 0 ? content[--i1] : null;
			} else if (c > 0) {
				p.content[--i] = t2.negate();
				t2 = i2 > 0 ? q.content[--i2].multiply(generic) : null;
			} else {
				Term t = t1.subtract(t2);
				if (t.signum() != 0) p.content[--i] = t;
				t1 = i1 > 0 ? content[--i1] : null;
				t2 = i2 > 0 ? q.content[--i2].multiply(generic) : 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);
		ArrayPolynomial q = (ArrayPolynomial) polynomial;
		ArrayPolynomial p = newinstance(size + q.size);
		int i = p.size;
		int i1 = size;
		int i2 = q.size;
		Term t1 = i1 > 0 ? content[--i1] : null;
		Term t2 = i2 > 0 ? q.content[--i2].multiply(monomial, generic) : null;
		while (t1 != null || t2 != null) {
			int c = t1 == null ? 1 : (t2 == null ? -1 : -ordering.compare(t1.monomial(), t2.monomial()));
			if (c < 0) {
				p.content[--i] = t1;
				t1 = i1 > 0 ? content[--i1] : null;
			} else if (c > 0) {
				p.content[--i] = t2.negate();
				t2 = i2 > 0 ? q.content[--i2].multiply(monomial, generic) : null;
			} else {
				Term t = t1.subtract(t2);
				if (t.signum() != 0) p.content[--i] = t;
				t1 = i1 > 0 ? content[--i1] : null;
				t2 = i2 > 0 ? q.content[--i2].multiply(monomial, generic) : null;
			}
		}
		p.resize(p.size - i);
		p.degree = degree(p);
		p.sugar = Math.max(sugar, q.sugar + monomial.degree());
		return p;
	}

	@Nonnull
	public Polynomial multiply(@Nonnull Polynomial that) {
		Polynomial p = valueOf(JsclInteger.valueOf(0));
		for (int i = 0; i < size; i++) {
			Term t = content[i];
			p = p.multiplyAndSubtract(t.monomial(), t.coef().negate(), that);
		}
		return p;
	}

	public Polynomial multiply(Generic generic) {
		if (generic.signum() == 0) return valueOf(JsclInteger.valueOf(0));
		if (generic.compareTo(JsclInteger.valueOf(1)) == 0) return this;
		ArrayPolynomial p = newinstance(size);
		for (int i = 0; i < size; i++) p.content[i] = content[i].multiply(generic);
		p.degree = degree;
		p.sugar = sugar;
		return p;
	}

	public Polynomial multiply(Monomial monomial) {
		if (defined) throw new UnsupportedOperationException();
		if (monomial.degree() == 0) return this;
		ArrayPolynomial p = newinstance(size);
		for (int i = 0; i < size; i++) p.content[i] = content[i].multiply(monomial);
		p.degree = degree + monomial.degree();
		p.sugar = sugar + monomial.degree();
		return p;
	}

	public Polynomial divide(Generic generic) throws ArithmeticException {
		if (generic.compareTo(JsclInteger.valueOf(1)) == 0) return this;
		ArrayPolynomial p = newinstance(size);
		for (int i = 0; i < size; i++) p.content[i] = content[i].divide(generic);
		p.degree = degree;
		p.sugar = sugar;
		return p;
	}

	public Polynomial divide(Monomial monomial) throws ArithmeticException {
		if (monomial.degree() == 0) return this;
		ArrayPolynomial p = newinstance(size);
		for (int i = 0; i < size; i++) p.content[i] = content[i].divide(monomial);
		p.degree = degree - monomial.degree();
		p.sugar = sugar - monomial.degree();
		return p;
	}

	public Polynomial gcd(Polynomial polynomial) {
		throw new UnsupportedOperationException();
	}

	public Generic gcd() {
		if (field) return coefficient(tail());
		Generic a = coefficient(JsclInteger.valueOf(0));
		for (int i = size - 1; i >= 0; i--) a = a.gcd(content[i].coef());
		return a.signum() == signum() ? a : a.negate();
	}

	public Monomial monomialGcd() {
		Monomial m = monomial(tail());
		for (int i = 0; i < size; i++) m = m.gcd(content[i].monomial());
		return m;
	}

	public int degree() {
		return degree;
	}

	public Polynomial valueOf(Polynomial polynomial) {
		ArrayPolynomial p = newinstance(0);
		p.init(polynomial);
		return p;
	}

	public Polynomial valueOf(Generic generic) {
		ArrayPolynomial p = newinstance(0);
		p.init(generic);
		return p;
	}

	public Polynomial valueOf(Monomial monomial) {
		ArrayPolynomial p = newinstance(0);
		p.init(monomial);
		return p;
	}

	public Polynomial freeze() {
		return this;
	}

	public Term head() {
		return size > 0 ? content[size - 1] : null;
	}

	public Term tail() {
		return size > 0 ? content[0] : null;
	}

	void init(Polynomial polynomial) {
		ArrayPolynomial q = (ArrayPolynomial) polynomial;
		init(q.size);
		System.arraycopy(q.content, 0, content, 0, size);
		degree = q.degree;
		sugar = q.sugar;
	}

	void init(Expression expression) {
		Map map = new TreeMap(ordering);
		int n = expression.size();
		for (int i = 0; i < n; i++) {
			Literal l = expression.literal(i);
			JsclInteger en = expression.coef(i);
			Monomial m = monomial(l);
			l = l.divide(m.literalValue());
			Generic a2 = coefficient(l.degree() > 0 ? en.multiply(Expression.valueOf(l)) : en);
			Generic a1 = (Generic) map.get(m);
			Generic a = a1 == null ? a2 : a1.add(a2);
			if (a.signum() == 0) map.remove(m);
			else map.put(m, a);
		}
		init(map.size());
		int sugar = 0;
		Iterator it = map.entrySet().iterator();
		for (int i = 0; i < size; i++) {
			Map.Entry e = (Map.Entry) it.next();
			Monomial m = (Monomial) e.getKey();
			Generic a = (Generic) e.getValue();
			content[i] = new Term(m, a);
			sugar = Math.max(sugar, m.degree());
		}
		degree = degree(this);
		this.sugar = sugar;
	}

	void init(Generic generic) {
		if (generic instanceof Expression) {
			init((Expression) generic);
		} else {
			Generic a = coefficient(generic);
			if (a.signum() != 0) {
				init(1);
				content[0] = new Term(monomial(Literal.newInstance()), a);
			} else init(0);
			degree = 0;
			sugar = 0;
		}
	}

	void init(Monomial monomial) {
		init(1);
		content[0] = new Term(monomial, coefficient(JsclInteger.valueOf(1)));
		degree = monomial.degree();
		sugar = monomial.degree();
	}

	protected ArrayPolynomial newinstance(int n) {
		return new ArrayPolynomial(n, monomialFactory, coefFactory);
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy