diff --git a/src/misc/lib/jscl.jar b/src/misc/lib/jscl.jar new file mode 100644 index 00000000..7da29a66 Binary files /dev/null and b/src/misc/lib/jscl.jar differ diff --git a/src/misc/src/jscl/editorengine/EditorEngine.java b/src/misc/src/jscl/editorengine/EditorEngine.java new file mode 100644 index 00000000..619115ae --- /dev/null +++ b/src/misc/src/jscl/editorengine/EditorEngine.java @@ -0,0 +1,58 @@ +package jscl.editorengine; + +import jscl.editor.Engine; +import jscl.editor.EngineException; +import bsh.Interpreter; +import bsh.EvalError; + +public class EditorEngine extends Engine { + Interpreter interp=new Interpreter(); + + public EditorEngine() throws EngineException { + try { + interp.eval("importCommands(\"/jscl/editorengine/commands\");\n" + +"mml(x) { return tomathml(x); }\n"); + } catch (EvalError e) { + throw new EngineException(e); + } + } + + public String eval(String str) throws EngineException { + int n=str.length()-1; + if(n<0 || "\n".equals(str.substring(n))) { + exec(str); + return str; + } else return eval0(str); + } + + public void exec(String str) throws EngineException { + try { + interp.eval(str); + } catch (EvalError e) { + throw new EngineException(e); + } + } + + String eval0(String str) throws EngineException { + try { + return interp.eval(commands(str)).toString(); + } catch (EvalError e) { + throw new EngineException(e); + } + } + + String commands(String str) { + return commands(str,false); + } + + String commands(String str, boolean found) { + for(int i=0;i=0 && (" "+cmds[i].toLowerCase()).equals(str.substring(n))) return commands(str.substring(0,n),true)+"."+cmds[i]+"()"; + } + str=str.replaceAll("\n",""); + return found?"jscl.math.Expression.valueOf(\""+str+"\")":str; + } + + static final String cmds[]=new String[] {"expand","factorize","elementary","simplify","numeric","toMathML","toJava"}; +} diff --git a/src/misc/src/jscl/editorengine/EditorEngineFactory.java b/src/misc/src/jscl/editorengine/EditorEngineFactory.java new file mode 100644 index 00000000..61fc96d6 --- /dev/null +++ b/src/misc/src/jscl/editorengine/EditorEngineFactory.java @@ -0,0 +1,11 @@ +package jscl.editorengine; + +import jscl.editor.Engine; +import jscl.editor.EngineFactory; +import jscl.editor.EngineException; + +public class EditorEngineFactory extends EngineFactory { + public Engine getEngine() throws EngineException { + return new EditorEngine(); + } +} diff --git a/src/misc/src/jscl/editorengine/commands/elementary.bsh b/src/misc/src/jscl/editorengine/commands/elementary.bsh new file mode 100644 index 00000000..f3c6cab7 --- /dev/null +++ b/src/misc/src/jscl/editorengine/commands/elementary.bsh @@ -0,0 +1,5 @@ +import jscl.math.Expression; + +String elementary(String expr) { + return Expression.valueOf(expr).elementary().toString(); +} diff --git a/src/misc/src/jscl/editorengine/commands/expand.bsh b/src/misc/src/jscl/editorengine/commands/expand.bsh new file mode 100644 index 00000000..0b7af2d2 --- /dev/null +++ b/src/misc/src/jscl/editorengine/commands/expand.bsh @@ -0,0 +1,5 @@ +import jscl.math.Expression; + +String expand(String expr) { + return Expression.valueOf(expr).expand().toString(); +} diff --git a/src/misc/src/jscl/editorengine/commands/factorize.bsh b/src/misc/src/jscl/editorengine/commands/factorize.bsh new file mode 100644 index 00000000..b21abe8e --- /dev/null +++ b/src/misc/src/jscl/editorengine/commands/factorize.bsh @@ -0,0 +1,5 @@ +import jscl.math.Expression; + +String factorize(String expr) { + return Expression.valueOf(expr).factorize().toString(); +} diff --git a/src/misc/src/jscl/editorengine/commands/numeric.bsh b/src/misc/src/jscl/editorengine/commands/numeric.bsh new file mode 100644 index 00000000..d1d61910 --- /dev/null +++ b/src/misc/src/jscl/editorengine/commands/numeric.bsh @@ -0,0 +1,5 @@ +import jscl.math.Expression; + +String numeric(String expr) { + return Expression.valueOf(expr).numeric().toString(); +} diff --git a/src/misc/src/jscl/editorengine/commands/simplify.bsh b/src/misc/src/jscl/editorengine/commands/simplify.bsh new file mode 100644 index 00000000..c8a049fc --- /dev/null +++ b/src/misc/src/jscl/editorengine/commands/simplify.bsh @@ -0,0 +1,5 @@ +import jscl.math.Expression; + +String simplify(String expr) { + return Expression.valueOf(expr).simplify().toString(); +} diff --git a/src/misc/src/jscl/editorengine/commands/tojava.bsh b/src/misc/src/jscl/editorengine/commands/tojava.bsh new file mode 100644 index 00000000..40e794e9 --- /dev/null +++ b/src/misc/src/jscl/editorengine/commands/tojava.bsh @@ -0,0 +1,5 @@ +import jscl.math.Expression; + +String tojava(String expr) { + return Expression.valueOf(expr).toJava(); +} diff --git a/src/misc/src/jscl/editorengine/commands/tomathml.bsh b/src/misc/src/jscl/editorengine/commands/tomathml.bsh new file mode 100644 index 00000000..81afd4f3 --- /dev/null +++ b/src/misc/src/jscl/editorengine/commands/tomathml.bsh @@ -0,0 +1,5 @@ +import jscl.math.Expression; + +String tomathml(String expr) { + return Expression.valueOf(expr).toMathML(); +} diff --git a/src/misc/src/jscl/math/Antiderivative.java b/src/misc/src/jscl/math/Antiderivative.java new file mode 100644 index 00000000..0b4f1a8a --- /dev/null +++ b/src/misc/src/jscl/math/Antiderivative.java @@ -0,0 +1,228 @@ +package jscl.math; + +import jscl.math.function.Frac; +import jscl.math.function.Inv; +import jscl.math.function.Log; +import jscl.math.function.Pow; +import jscl.math.function.Root; +import jscl.math.polynomial.Monomial; +import jscl.math.polynomial.Polynomial; +import jscl.math.polynomial.UnivariatePolynomial; + +public class Antiderivative { + UnivariatePolynomial factory; + PolynomialWithSyzygy syzygy; + Generic result; + + Antiderivative(Variable variable) { + factory=(UnivariatePolynomial)Polynomial.factory(variable); + syzygy=(PolynomialWithSyzygy)PolynomialWithSyzygy.factory(variable); + } + + public static Generic compute(Frac frac, Variable variable) { + Antiderivative s=new Antiderivative(variable); + s.compute(frac); + return s.getValue(); + } + + public static Generic compute(Root root, Variable variable) throws NotIntegrableException { + int d=root.degree(); + Generic a[]=root.parameters(); + boolean b=d>0; + b=b && a[0].negate().isIdentity(variable); + for(int i=1;i0?rs[i].normalize():rs[i]).genericValue()); + UnivariatePolynomial q[]=rs[0].squarefreeDecomposition(); + int m=q.length-1; + Generic s=JSCLInteger.valueOf(0); + for(int i=1;i<=m;i++) { + for(int j=0;j=0;i--) { + Generic c1=p.get(i+d2); + Generic c2=q.get(d2); + Generic c=c1.gcd(c2); + c1=c1.divide(c); + c2=c2.divide(c); + p=(PolynomialWithSyzygy)p.multiply(c2).subtract(q.multiply(monomial(Literal.valueOf(variable,i)),c1)).normalize(); + } + return p; + } + + public Polynomial gcd(Polynomial polynomial) { + Polynomial p=this; + Polynomial q=polynomial; + while(q.signum()!=0) { + Polynomial r=p.remainderUpToCoefficient(q); + p=q; + q=r; + } + return p; + } + + public Generic gcd() { + Generic a=super.gcd(); + for(int i=0;i0?literal[--i1]:null; + Literal l2=i2>0?expression.literal[--i2]:null; + while(l1!=null || l2!=null) { + int c=l1==null?1:(l2==null?-1:-l1.compareTo(l2)); + if(c<0) { + JSCLInteger en=coef[i1]; + --i; + ex.literal[i]=l1; + ex.coef[i]=en; + l1=i1>0?literal[--i1]:null; + } else if(c>0) { + JSCLInteger en=expression.coef[i2]; + --i; + ex.literal[i]=l2; + ex.coef[i]=en; + l2=i2>0?expression.literal[--i2]:null; + } else { + JSCLInteger en=coef[i1].add(expression.coef[i2]); + if(en.signum()!=0) { + --i; + ex.literal[i]=l1; + ex.coef[i]=en; + } + l1=i1>0?literal[--i1]:null; + l2=i2>0?expression.literal[--i2]:null; + } + } + ex.resize(ex.size-i); + return ex; + } + + public Generic add(Generic generic) { + if(generic instanceof Expression) { + return add((Expression)generic); + } else if(generic instanceof JSCLInteger || generic instanceof Rational) { + return add(valueof(generic)); + } else { + return generic.valueof(this).add(generic); + } + } + + public Expression subtract(Expression expression) { + return multiplyAndAdd(Literal.valueOf(),JSCLInteger.valueOf(-1),expression); + } + + public Generic subtract(Generic generic) { + if(generic instanceof Expression) { + return subtract((Expression)generic); + } else if(generic instanceof JSCLInteger || generic instanceof Rational) { + return subtract(valueof(generic)); + } else { + return generic.valueof(this).subtract(generic); + } + } + + Expression multiplyAndAdd(Literal lit, JSCLInteger integer, Expression expression) { + if(integer.signum()==0) return this; + Expression ex=newinstance(size+expression.size); + int i=ex.size; + int i1=size; + int i2=expression.size; + Literal l1=i1>0?literal[--i1]:null; + Literal l2=i2>0?expression.literal[--i2].multiply(lit):null; + while(l1!=null || l2!=null) { + int c=l1==null?1:(l2==null?-1:-l1.compareTo(l2)); + if(c<0) { + JSCLInteger en=coef[i1]; + --i; + ex.literal[i]=l1; + ex.coef[i]=en; + l1=i1>0?literal[--i1]:null; + } else if(c>0) { + JSCLInteger en=expression.coef[i2].multiply(integer); + --i; + ex.literal[i]=l2; + ex.coef[i]=en; + l2=i2>0?expression.literal[--i2].multiply(lit):null; + } else { + JSCLInteger en=coef[i1].add(expression.coef[i2].multiply(integer)); + if(en.signum()!=0) { + --i; + ex.literal[i]=l1; + ex.coef[i]=en; + } + l1=i1>0?literal[--i1]:null; + l2=i2>0?expression.literal[--i2].multiply(lit):null; + } + } + ex.resize(ex.size-i); + return ex; + } + + public Expression multiply(Expression expression) { + Expression ex=newinstance(0); + for(int i=0;i=0;i--) en=en.gcd(coef[i]); + return en; + } + + public Literal literalScm() { + Literal l=Literal.valueOf(); + for(int i=0;i1) { + Generic s=JSCLInteger.valueOf(0); + for(int i=0;i0) return 1; + else { + c=coef[i1].compareTo(expression.coef[i2]); + if(c<0) return -1; + else if(c>0) return 1; + l1=i1==0?null:literal[--i1]; + l2=i2==0?null:expression.literal[--i2]; + } + } + return 0; + } + + public int compareTo(Generic generic) { + if(generic instanceof Expression) { + return compareTo((Expression)generic); + } else if(generic instanceof JSCLInteger || generic instanceof Rational) { + return compareTo(valueof(generic)); + } else { + return generic.valueof(this).compareTo(generic); + } + } + + public static Expression valueOf(Variable variable) { + return valueOf(Literal.valueOf(variable)); + } + + public static Expression valueOf(Literal literal) { + return valueOf(literal,JSCLInteger.valueOf(1)); + } + + public static Expression valueOf(JSCLInteger integer) { + return valueOf(Literal.valueOf(),integer); + } + + public static Expression valueOf(Literal literal, JSCLInteger integer) { + Expression ex=new Expression(); + ex.init(literal,integer); + return ex; + } + + void init(Literal lit, JSCLInteger integer) { + if(integer.signum()!=0) { + init(1); + literal[0]=lit; + coef[0]=integer; + } else init(0); + } + + public static Expression valueOf(Rational rational) { + Expression ex=new Expression(); + ex.init(rational); + return ex; + } + + public static Expression valueOf(String str) throws ParseException { + int pos[]=new int[1]; + Generic a; + try { + a=(Generic)ExpressionParser.parser.parse(str,pos); + } catch (ParseException e) { + throw e; + } + Parser.skipWhitespaces(str,pos); + if(pos[0]0 && i>0) buffer.append("+"); + if(l.degree()==0) buffer.append(en); + else { + if(en.abs().compareTo(JSCLInteger.valueOf(1))==0) { + if(en.signum()<0) buffer.append("-"); + } else buffer.append(en).append("*"); + buffer.append(l); + } + } + return buffer.toString(); + } + + public String toJava() { + StringBuffer buffer=new StringBuffer(); + if(signum()==0) buffer.append("JSCLDouble.valueOf(0)"); + for(int i=0;i0) { + if(en.signum()<0) { + buffer.append(".subtract("); + en=(JSCLInteger)en.negate(); + } else buffer.append(".add("); + } + if(l.degree()==0) buffer.append(en.toJava()); + else { + if(en.abs().compareTo(JSCLInteger.valueOf(1))==0) { + if(en.signum()>0) buffer.append(l.toJava()); + else if(en.signum()<0) buffer.append(l.toJava()).append(".negate()"); + } else buffer.append(en.toJava()).append(".multiply(").append(l.toJava()).append(")"); + } + if(i>0) buffer.append(")"); + } + return buffer.toString(); + } + + public void toMathML(MathML element, Object data) { + MathML e1=element.element("mrow"); + if(signum()==0) { + MathML e2=element.element("mn"); + e2.appendChild(element.text("0")); + e1.appendChild(e2); + } + for(int i=0;i0 && i>0) { + MathML e2=element.element("mo"); + e2.appendChild(element.text("+")); + e1.appendChild(e2); + } + if(l.degree()==0) separateSign(e1,en); + else { + if(en.abs().compareTo(JSCLInteger.valueOf(1))==0) { + if(en.signum()<0) { + MathML e2=element.element("mo"); + e2.appendChild(element.text("-")); + e1.appendChild(e2); + } + } else separateSign(e1,en); + l.toMathML(e1,null); + } + } + element.appendChild(e1); + } + + public static void separateSign(MathML element, Generic generic) { + if(generic.signum()<0) { + MathML e1=element.element("mo"); + e1.appendChild(element.text("-")); + element.appendChild(e1); + generic.negate().toMathML(element,null); + } else generic.toMathML(element,null); + } + + protected Expression newinstance(int n) { + return new Expression(n); + } +} diff --git a/src/misc/src/jscl/math/ExpressionVariable.java b/src/misc/src/jscl/math/ExpressionVariable.java new file mode 100644 index 00000000..745a9a0c --- /dev/null +++ b/src/misc/src/jscl/math/ExpressionVariable.java @@ -0,0 +1,57 @@ +package jscl.math; + +import jscl.mathml.MathML; + +public class ExpressionVariable extends GenericVariable { + public ExpressionVariable(Generic generic) { + super(generic); + } + + public Generic substitute(Variable variable, Generic generic) { + if(isIdentity(variable)) return generic; + else return content.substitute(variable,generic); + } + + public Generic elementary() { + return content.elementary(); + } + + public Generic simplify() { + return content.simplify(); + } + + public String toString() { + StringBuffer buffer=new StringBuffer(); + buffer.append("(").append(content).append(")"); + return buffer.toString(); + } + + public String toJava() { + StringBuffer buffer=new StringBuffer(); + buffer.append("(").append(content.toJava()).append(")"); + return buffer.toString(); + } + + public void toMathML(MathML element, Object data) { + int exponent=data instanceof Integer?((Integer)data).intValue():1; + if(exponent==1) bodyToMathML(element); + else { + MathML e1=element.element("msup"); + bodyToMathML(e1); + MathML e2=element.element("mn"); + e2.appendChild(element.text(String.valueOf(exponent))); + e1.appendChild(e2); + element.appendChild(e1); + } + } + + void bodyToMathML(MathML element) { + MathML e1=element.element("mfenced"); + content.toMathML(e1,null); + element.appendChild(e1); + } + + protected Variable newinstance() { + return new ExpressionVariable(null); + } +} diff --git a/src/misc/src/jscl/math/Factorization.java b/src/misc/src/jscl/math/Factorization.java new file mode 100644 index 00000000..5c72ea42 --- /dev/null +++ b/src/misc/src/jscl/math/Factorization.java @@ -0,0 +1,290 @@ +package jscl.math; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import jscl.math.polynomial.Basis; +import jscl.math.polynomial.Monomial; +import jscl.math.polynomial.Ordering; +import jscl.math.polynomial.Polynomial; +import jscl.util.ArrayComparator; +import jscl.util.ArrayUtils; + +public class Factorization { + Polynomial factory; + Generic result; + + Factorization(Polynomial factory) { + this.factory=factory; + } + + public static Generic compute(Generic generic) { + try { + return GenericVariable.content(factorize(generic.integerValue())); + } catch (NotIntegerException e) { + Factorization f=new Factorization(Polynomial.factory(generic.variables(),Monomial.iteratorOrdering,-1)); + f.computeValue(generic); + return f.getValue(); + } + } + + static Generic factorize(JSCLInteger integer) { + Generic n[]=integer.gcdAndNormalize(); + Generic s=n[1]; + Generic a=JSCLInteger.valueOf(1); + Generic p=JSCLInteger.valueOf(2); + while(s.compareTo(JSCLInteger.valueOf(1))>0) { + Generic q[]=s.divideAndRemainder(p); + if(q[0].compareTo(p)<0) { + p=s; + q=s.divideAndRemainder(p); + } + if(q[1].signum()==0) { + a=a.multiply(expression(p,true)); + s=q[0]; + } else p=p.add(JSCLInteger.valueOf(1)); + } + return a.multiply(n[0]); + } + + void computeValue(Generic generic) { + Debug.println("factorization"); + Polynomial n[]=factory.valueof(generic).gcdAndNormalize(); + Monomial m=n[1].monomialGcd(); + Polynomial s=n[1].divide(m); + Generic a=JSCLInteger.valueOf(1); + Divisor d[]=new Divisor[2]; + Monomial p[]=new Monomial[2]; + Monomial q[]=new Monomial[2]; + d[1]=new Divisor(s.head().monomial()); + loop: while(d[1].hasNext()) { + p[1]=(Monomial)d[1].next(); + q[1]=d[1].complementary(); + d[0]=new Divisor(s.tail().monomial()); + while(d[0].hasNext()) { + p[0]=(Monomial)d[0].next(); + q[0]=d[0].complementary(); + if(p[1].compareTo(p[0])<=0) continue loop; + Debug.println(toString(p)+" * "+toString(q)+" = "+s); + if(ArrayComparator.comparator.compare(q,p)<0) { + a=a.multiply(expression(s.genericValue())); + break loop; + } else { + Debug.increment(); + Polynomial r[]=remainder(s,polynomial(s,p),terminator(s)); + Debug.decrement(); + if(r[0].signum()==0) { + a=a.multiply(expression(r[1].genericValue())); + s=r[2]; + d[1].divide(); + d[0].divide(); + continue loop; + } + } + } + } + result=a.multiply(n[0].multiply(m).genericValue()); + } + + static Polynomial[] remainder(Polynomial s, Polynomial p, Generic t[]) { + Polynomial zero=s.valueof(JSCLInteger.valueOf(0)); + Generic a[]=Basis.augment(t,s.remainderUpToCoefficient(p).elements()); + Variable unk[]=Basis.augmentUnknown(new Variable[] {},p.elements()); + { + Variable u=unk[unk.length-1]; + System.arraycopy(unk,0,unk,1,unk.length-1); + unk[0]=u; + } + Generic be[][]=Linearization.compute(Basis.compute(a,unk,Monomial.lexicographic,0,Basis.DEGREE).elements(),unk); + for(int i=0;i1) { + flag=false; + Polynomial r[]=linearize(p,t); + for(int j=0;j0) return 1; + else { + GenericVariable v=(GenericVariable)variable; + return content.compareTo(v.content); + } + } + + public static GenericVariable valueOf(Generic generic) { + return valueOf(generic,false); + } + + public static GenericVariable valueOf(Generic generic, boolean integer) { + if(integer) return new IntegerVariable(generic); + else return new ExpressionVariable(generic); + } + + public String toString() { + return content.toString(); + } + + public String toJava() { + return content.toJava(); + } + + public void toMathML(MathML element, Object data) { + content.toMathML(element,data); + } +} diff --git a/src/misc/src/jscl/math/IntegerVariable.java b/src/misc/src/jscl/math/IntegerVariable.java new file mode 100644 index 00000000..d562d02a --- /dev/null +++ b/src/misc/src/jscl/math/IntegerVariable.java @@ -0,0 +1,57 @@ +package jscl.math; + +import jscl.mathml.MathML; + +class IntegerVariable extends GenericVariable { + IntegerVariable(Generic generic) { + super(generic); + } + + public Generic substitute(Variable variable, Generic generic) { + if(isIdentity(variable)) return generic; + else return content.substitute(variable,generic); + } + + public Generic elementary() { + return content.elementary(); + } + + public Generic simplify() { + return content.simplify(); + } + + public String toString() { + StringBuffer buffer=new StringBuffer(); + buffer.append("(").append(content).append(")"); + return buffer.toString(); + } + + public String toJava() { + StringBuffer buffer=new StringBuffer(); + buffer.append("(").append(content.toJava()).append(")"); + return buffer.toString(); + } + + public void toMathML(MathML element, Object data) { + int exponent=data instanceof Integer?((Integer)data).intValue():1; + if(exponent==1) bodyToMathML(element); + else { + MathML e1=element.element("msup"); + bodyToMathML(e1); + MathML e2=element.element("mn"); + e2.appendChild(element.text(String.valueOf(exponent))); + e1.appendChild(e2); + element.appendChild(e1); + } + } + + void bodyToMathML(MathML element) { + MathML e1=element.element("mfenced"); + content.toMathML(e1,null); + element.appendChild(e1); + } + + protected Variable newinstance() { + return new IntegerVariable(null); + } +} diff --git a/src/misc/src/jscl/math/JSCLBoolean.java b/src/misc/src/jscl/math/JSCLBoolean.java new file mode 100644 index 00000000..79fc2adc --- /dev/null +++ b/src/misc/src/jscl/math/JSCLBoolean.java @@ -0,0 +1,16 @@ +package jscl.math; + +public class JSCLBoolean extends ModularInteger { + public static final JSCLBoolean factory=new JSCLBoolean(0); + + public JSCLBoolean(long content) { + super(content,2); + } + + protected ModularInteger newinstance(long content) { + return content%2==0?zero:one; + } + + private static final JSCLBoolean zero=factory; + private static final JSCLBoolean one=new JSCLBoolean(1); +} diff --git a/src/misc/src/jscl/math/JSCLInteger.java b/src/misc/src/jscl/math/JSCLInteger.java new file mode 100644 index 00000000..e65f4187 --- /dev/null +++ b/src/misc/src/jscl/math/JSCLInteger.java @@ -0,0 +1,330 @@ +package jscl.math; + +import java.math.BigInteger; +import jscl.mathml.MathML; + +public final class JSCLInteger extends Generic { + public static final JSCLInteger factory=new JSCLInteger(BigInteger.valueOf(0)); + final BigInteger content; + + public JSCLInteger(BigInteger content) { + this.content=content; + } + + public BigInteger content() { + return content; + } + + public JSCLInteger add(JSCLInteger integer) { + return new JSCLInteger(content.add(integer.content)); + } + + public Generic add(Generic generic) { + if(generic instanceof JSCLInteger) { + return add((JSCLInteger)generic); + } else { + return generic.valueof(this).add(generic); + } + } + + public JSCLInteger subtract(JSCLInteger integer) { + return new JSCLInteger(content.subtract(integer.content)); + } + + public Generic subtract(Generic generic) { + if(generic instanceof JSCLInteger) { + return subtract((JSCLInteger)generic); + } else { + return generic.valueof(this).subtract(generic); + } + } + + public JSCLInteger multiply(JSCLInteger integer) { + return new JSCLInteger(content.multiply(integer.content)); + } + + public Generic multiply(Generic generic) { + if(generic instanceof JSCLInteger) { + return multiply((JSCLInteger)generic); + } else { + return generic.multiply(this); + } + } + + public JSCLInteger divide(JSCLInteger integer) throws ArithmeticException { + JSCLInteger e[]=divideAndRemainder(integer); + if(e[1].signum()==0) return e[0]; + else throw new NotDivisibleException(); + } + + public Generic divide(Generic generic) throws ArithmeticException { + if(generic instanceof JSCLInteger) { + return divide((JSCLInteger)generic); + } else { + return generic.valueof(this).divide(generic); + } + } + + public JSCLInteger[] divideAndRemainder(JSCLInteger integer) throws ArithmeticException { + BigInteger b[]=content.divideAndRemainder(integer.content); + return new JSCLInteger[] {new JSCLInteger(b[0]),new JSCLInteger(b[1])}; + } + + public Generic[] divideAndRemainder(Generic generic) throws ArithmeticException { + if(generic instanceof JSCLInteger) { + return divideAndRemainder((JSCLInteger)generic); + } else { + return generic.valueof(this).divideAndRemainder(generic); + } + } + + public JSCLInteger remainder(JSCLInteger integer) throws ArithmeticException { + return new JSCLInteger(content.remainder(integer.content)); + } + + public Generic remainder(Generic generic) throws ArithmeticException { + if(generic instanceof JSCLInteger) { + return remainder((JSCLInteger)generic); + } else { + return generic.valueof(this).remainder(generic); + } + } + + public JSCLInteger gcd(JSCLInteger integer) { + return new JSCLInteger(content.gcd(integer.content)); + } + + public Generic gcd(Generic generic) { + if(generic instanceof JSCLInteger) { + return gcd((JSCLInteger)generic); + } else { + return generic.valueof(this).gcd(generic); + } + } + + public Generic gcd() { + return new JSCLInteger(BigInteger.valueOf(signum())); + } + + public Generic pow(int exponent) { + return new JSCLInteger(content.pow(exponent)); + } + + public Generic negate() { + return new JSCLInteger(content.negate()); + } + + public int signum() { + return content.signum(); + } + + public int degree() { + return 0; + } + + public JSCLInteger mod(JSCLInteger integer) { + return new JSCLInteger(content.mod(integer.content)); + } + + public JSCLInteger modPow(JSCLInteger exponent, JSCLInteger integer) { + return new JSCLInteger(content.modPow(exponent.content,integer.content)); + } + + public JSCLInteger modInverse(JSCLInteger integer) { + return new JSCLInteger(content.modInverse(integer.content)); + } + + public JSCLInteger phi() { + if(signum()==0) return this; + Generic a=factorize(); + Generic p[]=a.productValue(); + Generic s=JSCLInteger.valueOf(1); + for(int i=0;i0; + } + if(b) r[k++]=m; + m=m.add(JSCLInteger.valueOf(1)); + } + return k>0?r:new JSCLInteger[0]; + } + + public JSCLInteger sqrt() { + return nthrt(2); + } + + public JSCLInteger nthrt(int n) { +// return JSCLInteger.valueOf((int)Math.pow((double)intValue(),1./n)); + if(signum()==0) return JSCLInteger.valueOf(0); + else if(signum()<0) { + if(n%2==0) throw new ArithmeticException(); + else return (JSCLInteger)((JSCLInteger)negate()).nthrt(n).negate(); + } else { + Generic x0; + Generic x=this; + do { + x0=x; + x=divideAndRemainder(x.pow(n-1))[0].add(x.multiply(JSCLInteger.valueOf(n-1))).divideAndRemainder(JSCLInteger.valueOf(n))[0]; + } while(x.compareTo(x0)<0); + return x0.integerValue(); + } + } + + public Generic antiderivative(Variable variable) throws NotIntegrableException { + return multiply(variable.expressionValue()); + } + + public Generic derivative(Variable variable) { + return JSCLInteger.valueOf(0); + } + + public Generic substitute(Variable variable, Generic generic) { + return this; + } + + public Generic expand() { + return this; + } + + public Generic factorize() { + return Factorization.compute(this); + } + + public Generic elementary() { + return this; + } + + public Generic simplify() { + return this; + } + + public Generic numeric() { + return new NumericWrapper(this); + } + + public Generic valueof(Generic generic) { + return new JSCLInteger(((JSCLInteger)generic).content); + } + + public Generic[] sumValue() { + if(content.signum()==0) return new Generic[0]; + else return new Generic[] {this}; + } + + public Generic[] productValue() throws NotProductException { + if(content.compareTo(BigInteger.valueOf(1))==0) return new Generic[0]; + else return new Generic[] {this}; + } + + public Power powerValue() throws NotPowerException { + if(content.signum()<0) throw new NotPowerException(); + else return new Power(this,1); + } + + public Expression expressionValue() throws NotExpressionException { + return Expression.valueOf(this); + } + + public JSCLInteger integerValue() throws NotIntegerException { + return this; + } + + public Variable variableValue() throws NotVariableException { + throw new NotVariableException(); + } + + public Variable[] variables() { + return new Variable[0]; + } + + public boolean isPolynomial(Variable variable) { + return true; + } + + public boolean isConstant(Variable variable) { + return true; + } + + public int intValue() { + return content.intValue(); + } + + public int compareTo(JSCLInteger integer) { + return content.compareTo(integer.content); + } + + public int compareTo(Generic generic) { + if(generic instanceof JSCLInteger) { + return compareTo((JSCLInteger)generic); + } else { + return generic.valueof(this).compareTo(generic); + } + } + + private static final JSCLInteger ZERO=new JSCLInteger(BigInteger.valueOf(0)); + private static final JSCLInteger ONE=new JSCLInteger(BigInteger.valueOf(1)); + + public static JSCLInteger valueOf(long val) { + switch((int)val) { + case 0: + return ZERO; + case 1: + return ONE; + default: + return new JSCLInteger(BigInteger.valueOf(val)); + } + } + + public static JSCLInteger valueOf(String str) { + return new JSCLInteger(new BigInteger(str)); + } + + public String toString() { + return content.toString(); + } + + public String toJava() { + return "JSCLDouble.valueOf("+content+")"; + } + + public void toMathML(MathML element, Object data) { + int exponent=data instanceof Integer?((Integer)data).intValue():1; + if(exponent==1) bodyToMathML(element); + else { + MathML e1=element.element("msup"); + bodyToMathML(e1); + MathML e2=element.element("mn"); + e2.appendChild(element.text(String.valueOf(exponent))); + e1.appendChild(e2); + element.appendChild(e1); + } + } + + void bodyToMathML(MathML element) { + MathML e1=element.element("mn"); + e1.appendChild(element.text(String.valueOf(content))); + element.appendChild(e1); + } +} diff --git a/src/misc/src/jscl/math/JSCLVector.java b/src/misc/src/jscl/math/JSCLVector.java new file mode 100644 index 00000000..6a1622b6 --- /dev/null +++ b/src/misc/src/jscl/math/JSCLVector.java @@ -0,0 +1,476 @@ +package jscl.math; + +import jscl.math.function.Conjugate; +import jscl.math.function.Frac; +import jscl.mathml.MathML; +import jscl.util.ArrayComparator; + +public class JSCLVector extends Generic { + protected final Generic element[]; + protected final int n; + + public JSCLVector(Generic element[]) { + this.element=element; + n=element.length; + } + + public Generic[] elements() { + return element; + } + + public JSCLVector add(JSCLVector vector) { + JSCLVector v=(JSCLVector)newinstance(); + for(int i=0;i0) return 1; + } + return 0; + } + + public int degree() { + return 0; + } + + public Generic antiderivative(Variable variable) throws NotIntegrableException { + JSCLVector v=(JSCLVector)newinstance(); + for(int i=0;i0) { + for(int j=i;j0 && (j>i || i>=p)) s=!s; + } + } + } + return s; + } + + static int combination(int l, int n) { + if(n<=2) return l; + int b[]=new int[1]; + int l1=decimation(l,n,b); + int c=combination(l1,n-1); + return (c<<1)+b[0]; + } + + static int location(int c, int n) { + if(n<=2) return c; + int c1=c>>1; + int b=c&1; + int l1=location(c1,n-1); + return dilatation(l1,n,new int[] {b}); + } + + static int decimation(int l, int n, int b[]) { + int p=grade(l,n-1,1); + int p1=(p+1)>>1; + b[0]=p&1; + return l-sum(p1,n-1); + } + + static int dilatation(int l, int n, int b[]) { + int p1=grade(l,n-1); + return l+sum(p1+b[0],n-1); + } + + static int grade(int l, int n) { + return grade(l,n,0); + } + + static int grade(int l, int n, int d) { + int s=0, p=0; + while(true) { + s+=binomial(n,p>>d); + if(s<=l) p++; + else break; + } + return p; + } + + static int sum(int p, int n) { + int q=0, s=0; + while(q1;n>>=1) i++; + return i; + } + + int[][] operator() { + return operator; + } +} diff --git a/src/misc/src/jscl/math/Literal.java b/src/misc/src/jscl/math/Literal.java new file mode 100644 index 00000000..d4c4c8d2 --- /dev/null +++ b/src/misc/src/jscl/math/Literal.java @@ -0,0 +1,368 @@ +package jscl.math; + +import java.util.Iterator; +import java.util.Map; +import java.util.TreeMap; +import jscl.math.function.Frac; +import jscl.math.function.Pow; +import jscl.math.polynomial.Monomial; +import jscl.mathml.MathML; + +public class Literal implements Comparable { + Variable variable[]; + int power[]; + int degree; + int size; + + Literal() {} + + Literal(int size) { + init(size); + } + + public int size() { + return size; + } + + public Variable variable(int n) { + return variable[n]; + } + + public int power(int n) { + return power[n]; + } + + void init(int size) { + variable=new Variable[size]; + power=new int[size]; + this.size=size; + } + + void resize(int size) { + if(size0) { + int s=literal.power[i2]; + l.variable[i]=v2; + l.power[i]=s; + l.degree+=s; + i++; + i2++; + v2=i20) { + throw new NotDivisibleException(); + } else { + int s=power[i1]-literal.power[i2]; + if(s<0) throw new NotDivisibleException(); + else if(s==0); + else { + l.variable[i]=v1; + l.power[i]=s; + l.degree+=s; + i++; + } + i1++; + i2++; + v1=i10) { + i2++; + v2=i20) { + int s=literal.power[i2]; + l.variable[i]=v2; + l.power[i]=s; + l.degree+=s; + i++; + i2++; + v2=i20) return 1; + else { + int c1=power[i1]; + int c2=literal.power[i2]; + if(c1c2) return 1; + v1=i1==0?null:variable[--i1]; + v2=i2==0?null:literal.variable[--i2]; + } + } + return 0; + } + + public int compareTo(Object o) { + return compareTo((Literal)o); + } + + public static Literal valueOf() { + return new Literal(0); + } + + public static Literal valueOf(Variable variable) { + return valueOf(variable,1); + } + + public static Literal valueOf(Variable variable, int power) { + Literal l=new Literal(); + l.init(variable,power); + return l; + } + + void init(Variable var, int pow) { + if(pow!=0) { + init(1); + variable[0]=var; + power[0]=pow; + degree=pow; + } else init(0); + } + + public static Literal valueOf(Monomial monomial) { + Literal l=new Literal(); + l.init(monomial); + return l; + } + + void init(Monomial monomial) { + Map map=new TreeMap(); + Variable unk[]=monomial.unknown(); + for(int i=0;i0) map.put(unk[i],new Integer(c)); + } + init(map.size()); + Iterator it=map.entrySet().iterator(); + for(int i=0;it.hasNext();i++) { + Map.Entry e=(Map.Entry)it.next(); + Variable v=(Variable)e.getKey(); + int c=((Integer)e.getValue()).intValue(); + variable[i]=v; + power[i]=c; + degree+=c; + } + } + + Map content() { + Map map=new TreeMap(); + for(int i=0;i0) buffer.append("*"); + Variable v=variable[i]; + int c=power[i]; + if(c==1) buffer.append(v); + else { + if(v instanceof Frac || v instanceof Pow) { + buffer.append("(").append(v).append(")"); + } else buffer.append(v); + buffer.append("^").append(c); + } + } + return buffer.toString(); + } + + public String toJava() { + StringBuffer buffer=new StringBuffer(); + if(degree==0) buffer.append("JSCLDouble.valueOf(1)"); + for(int i=0;i0) buffer.append(".multiply("); + Variable v=variable[i]; + int c=power[i]; + buffer.append(v.toJava()); + if(c==1); + else buffer.append(".pow(").append(c).append(")"); + if(i>0) buffer.append(")"); + } + return buffer.toString(); + } + + public void toMathML(MathML element, Object data) { + if(degree==0) { + MathML e1=element.element("mn"); + e1.appendChild(element.text("1")); + element.appendChild(e1); + } + for(int i=0;i0?element[0].length:0; + } + + public Generic[][] elements() { + return element; + } + + public Matrix add(Matrix matrix) { + Matrix m=(Matrix)newinstance(); + for(int i=0;i0) return 1; + } + } + return 0; + } + + public int degree() { + return 0; + } + + public Generic antiderivative(Variable variable) throws NotIntegrableException { + Matrix m=(Matrix)newinstance(); + for(int i=0;i1) { + Generic a=JSCLInteger.valueOf(0); + for(int i=0;i0) return element[0][0]; + else return JSCLInteger.valueOf(0); + } + + public Generic conjugate() { + Matrix m=(Matrix)newinstance(); + for(int i=0;i0?vector[0].n:0][vector.length]); + for(int i=0;i0?1:0; + } + + public int degree() { + return 0; + } + + public Generic antiderivative(Variable variable) throws NotIntegrableException { + throw new UnsupportedOperationException(); + } + + public Generic derivative(Variable variable) { + throw new UnsupportedOperationException(); + } + + public Generic substitute(Variable variable, Generic generic) { + throw new UnsupportedOperationException(); + } + + public Generic expand() { + throw new UnsupportedOperationException(); + } + + public Generic factorize() { + throw new UnsupportedOperationException(); + } + + public Generic elementary() { + throw new UnsupportedOperationException(); + } + + public Generic simplify() { + throw new UnsupportedOperationException(); + } + + public Generic numeric() { + throw new UnsupportedOperationException(); + } + + public Generic valueof(Generic generic) { + if(generic instanceof ModularInteger) { + return newinstance(((ModularInteger)generic).content); + } else { + return newinstance(((JSCLInteger)generic).content().mod(BigInteger.valueOf(modulo)).intValue()); + } + } + + public Generic[] sumValue() { + throw new UnsupportedOperationException(); + } + + public Generic[] productValue() throws NotProductException { + throw new UnsupportedOperationException(); + } + + public Power powerValue() throws NotPowerException { + throw new UnsupportedOperationException(); + } + + public Expression expressionValue() throws NotExpressionException { + return Expression.valueOf(integerValue()); + } + + public JSCLInteger integerValue() throws NotIntegerException { + return JSCLInteger.valueOf(content); + } + + public Variable variableValue() throws NotVariableException { + throw new UnsupportedOperationException(); + } + + public Variable[] variables() { + throw new UnsupportedOperationException(); + } + + public boolean isPolynomial(Variable variable) { + throw new UnsupportedOperationException(); + } + + public boolean isConstant(Variable variable) { + throw new UnsupportedOperationException(); + } + + public int compareTo(ModularInteger integer) { + return contentinteger.content?1:0; + } + + public int compareTo(Generic generic) { + if(generic instanceof ModularInteger) { + return compareTo((ModularInteger)generic); + } else if(generic instanceof JSCLInteger) { + return compareTo(valueof(generic)); + } else { + throw new UnsupportedOperationException(); + } + } + + public static ModularInteger factory(int modulo) { + return new ModularInteger(0,modulo); + } + + public String toString() { + return ""+content; + } + + public String toJava() { + throw new UnsupportedOperationException(); + } + + public void toMathML(MathML element, Object data) { + throw new UnsupportedOperationException(); + } + + protected ModularInteger newinstance(long content) { + return new ModularInteger(content,modulo); + } +} diff --git a/src/misc/src/jscl/math/NotDivisibleException.java b/src/misc/src/jscl/math/NotDivisibleException.java new file mode 100644 index 00000000..29ac1bac --- /dev/null +++ b/src/misc/src/jscl/math/NotDivisibleException.java @@ -0,0 +1,9 @@ +package jscl.math; + +public class NotDivisibleException extends ArithmeticException { + public NotDivisibleException() {} + + public NotDivisibleException(String s) { + super(s); + } +} diff --git a/src/misc/src/jscl/math/NotExpressionException.java b/src/misc/src/jscl/math/NotExpressionException.java new file mode 100644 index 00000000..b1daf564 --- /dev/null +++ b/src/misc/src/jscl/math/NotExpressionException.java @@ -0,0 +1,9 @@ +package jscl.math; + +public class NotExpressionException extends ArithmeticException { + public NotExpressionException() {} + + public NotExpressionException(String s) { + super(s); + } +} diff --git a/src/misc/src/jscl/math/NotIntegerException.java b/src/misc/src/jscl/math/NotIntegerException.java new file mode 100644 index 00000000..053c65d8 --- /dev/null +++ b/src/misc/src/jscl/math/NotIntegerException.java @@ -0,0 +1,9 @@ +package jscl.math; + +public class NotIntegerException extends ArithmeticException { + public NotIntegerException() {} + + public NotIntegerException(String s) { + super(s); + } +} diff --git a/src/misc/src/jscl/math/NotIntegrableException.java b/src/misc/src/jscl/math/NotIntegrableException.java new file mode 100644 index 00000000..41017f32 --- /dev/null +++ b/src/misc/src/jscl/math/NotIntegrableException.java @@ -0,0 +1,9 @@ +package jscl.math; + +public class NotIntegrableException extends ArithmeticException { + public NotIntegrableException() {} + + public NotIntegrableException(String s) { + super(s); + } +} diff --git a/src/misc/src/jscl/math/NotPowerException.java b/src/misc/src/jscl/math/NotPowerException.java new file mode 100644 index 00000000..eaa5ed69 --- /dev/null +++ b/src/misc/src/jscl/math/NotPowerException.java @@ -0,0 +1,9 @@ +package jscl.math; + +public class NotPowerException extends ArithmeticException { + public NotPowerException() {} + + public NotPowerException(String s) { + super(s); + } +} diff --git a/src/misc/src/jscl/math/NotProductException.java b/src/misc/src/jscl/math/NotProductException.java new file mode 100644 index 00000000..c0a35ed1 --- /dev/null +++ b/src/misc/src/jscl/math/NotProductException.java @@ -0,0 +1,9 @@ +package jscl.math; + +public class NotProductException extends ArithmeticException { + public NotProductException() {} + + public NotProductException(String s) { + super(s); + } +} diff --git a/src/misc/src/jscl/math/NotVariableException.java b/src/misc/src/jscl/math/NotVariableException.java new file mode 100644 index 00000000..46580201 --- /dev/null +++ b/src/misc/src/jscl/math/NotVariableException.java @@ -0,0 +1,9 @@ +package jscl.math; + +public class NotVariableException extends ArithmeticException { + public NotVariableException() {} + + public NotVariableException(String s) { + super(s); + } +} diff --git a/src/misc/src/jscl/math/NumericWrapper.java b/src/misc/src/jscl/math/NumericWrapper.java new file mode 100644 index 00000000..b3d852c3 --- /dev/null +++ b/src/misc/src/jscl/math/NumericWrapper.java @@ -0,0 +1,344 @@ +package jscl.math; + +import jscl.math.function.Constant; +import jscl.math.numeric.JSCLDouble; +import jscl.math.numeric.Numeric; +import jscl.math.numeric.NumericMatrix; +import jscl.math.numeric.NumericVector; +import jscl.mathml.MathML; + +public final class NumericWrapper extends Generic { + final Numeric content; + + public NumericWrapper(JSCLInteger integer) { + content=JSCLDouble.valueOf(integer.content().doubleValue()); + } + + public NumericWrapper(Rational rational) { + content=JSCLDouble.valueOf(rational.numerator().doubleValue()/rational.denominator().doubleValue()); + } + + public NumericWrapper(JSCLVector vector) { + Numeric v[]=new Numeric[vector.n]; + for(int i=0;i0) return 1; + else return numerator.compareTo(rational.numerator); + } + + public int compareTo(Generic generic) { + if(generic instanceof Rational) { + return compareTo((Rational)generic); + } else if(generic instanceof JSCLInteger) { + return compareTo(valueof(generic)); + } else { + return generic.valueof(this).compareTo(generic); + } + } + + public String toString() { + StringBuffer buffer=new StringBuffer(); + try { + buffer.append(integerValue()); + } catch (NotIntegerException e) { + buffer.append(numerator); + buffer.append("/"); + buffer.append(denominator); + } + return buffer.toString(); + } + + public String toJava() { + return "JSCLDouble.valueOf("+numerator+"/"+denominator+")"; + } + + public void toMathML(MathML element, Object data) { + int exponent=data instanceof Integer?((Integer)data).intValue():1; + if(exponent==1) bodyToMathML(element); + else { + MathML e1=element.element("msup"); + bodyToMathML(e1); + MathML e2=element.element("mn"); + e2.appendChild(element.text(String.valueOf(exponent))); + e1.appendChild(e2); + element.appendChild(e1); + } + } + + void bodyToMathML(MathML element) { + try { + MathML e1=element.element("mn"); + e1.appendChild(element.text(String.valueOf(integerValue()))); + element.appendChild(e1); + } catch (NotIntegerException e) { + MathML e1=element.element("mfrac"); + MathML e2=element.element("mn"); + e2.appendChild(element.text(String.valueOf(numerator))); + e1.appendChild(e2); + e2=element.element("mn"); + e2.appendChild(element.text(String.valueOf(denominator))); + e1.appendChild(e2); + element.appendChild(e1); + } + } +} diff --git a/src/misc/src/jscl/math/Simplification.java b/src/misc/src/jscl/math/Simplification.java new file mode 100644 index 00000000..d1f2eb9c --- /dev/null +++ b/src/misc/src/jscl/math/Simplification.java @@ -0,0 +1,226 @@ +package jscl.math; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; +import jscl.math.function.Cubic; +import jscl.math.function.Frac; +import jscl.math.function.NotRootException; +import jscl.math.function.Pow; +import jscl.math.function.Root; +import jscl.math.function.Sqrt; +import jscl.math.polynomial.Basis; +import jscl.math.polynomial.Monomial; +import jscl.math.polynomial.Polynomial; +import jscl.math.polynomial.UnivariatePolynomial; + +public class Simplification { + Map cache=new TreeMap(); + Generic result; + List constraint; + boolean linear; + + Simplification() {} + + public static Generic compute(Generic generic) { + Simplification s=new Simplification(); + s.computeValue(generic); + return s.getValue(); + } + + void computeValue(Generic generic) { + Debug.println("simplification"); + Debug.increment(); + Variable t=new TechnicalVariable("t"); + linear=false; + constraint=new ArrayList(); + process(new Constraint(t,t.expressionValue().subtract(generic),false)); + UnivariatePolynomial p=polynomial(t); + switch(p.degree()) { + case 0: + result=generic; + break; + case 1: + result=new Root(p,0).evalsimp(); + break; +// case 2: +// int n=branch(generic,p); +// if(n1); + } catch (NotRootException e) { + co=linearConstraint(v); + } + } else if(v instanceof Root) { + try { + Root r=(Root)v; + int d=r.degree(); + int n=r.subscript().integerValue().intValue(); + Generic g[]=r.parameters(); + if(linear) co=linearConstraint(v); + if(co==null) co=new Constraint(v,Root.sigma(g,d-n).multiply(JSCLInteger.valueOf(-1).pow(d-n)).multiply(g[d]).subtract(g[n]),d>1); + } catch (NotIntegerException e) { + co=linearConstraint(v); + } + } else co=linearConstraint(v); + if(co!=null) constraint.add(co); + } + } + + Constraint linearConstraint(Variable v) { + Generic s; + Object o=cache.get(v); + if(o!=null) s=(Generic)o; + else { + s=v.simplify(); + cache.put(v,s); + } + Generic a=v.expressionValue().subtract(s); + if(a.signum()!=0) return new Constraint(v,a,false); + else return null; + } + + Generic getValue() { + return result; + } +} + +class Constraint { + Variable unknown; + Generic generic; + boolean reduce; + + Constraint(Variable unknown, Generic generic, boolean reduce) { + this.unknown=unknown; + this.generic=generic; + this.reduce=reduce; + } + + Constraint(Variable unknown) { + this(unknown,null,false); + } + + public boolean equals(Object obj) { + return unknown.compareTo(((Constraint)obj).unknown)==0; + } +} diff --git a/src/misc/src/jscl/math/TechnicalVariable.java b/src/misc/src/jscl/math/TechnicalVariable.java new file mode 100644 index 00000000..06cfbfc1 --- /dev/null +++ b/src/misc/src/jscl/math/TechnicalVariable.java @@ -0,0 +1,96 @@ +package jscl.math; + +public class TechnicalVariable extends Variable { + public int subscript[]; + + public TechnicalVariable(String name) { + this(name,new int[0]); + } + + public TechnicalVariable(String name, int subscript[]) { + super(name); + this.subscript=subscript; + } + + public Generic antiderivative(Variable variable) throws NotIntegrableException { + throw new NotIntegrableException(); + } + + public Generic derivative(Variable variable) { + if(isIdentity(variable)) return JSCLInteger.valueOf(1); + else return JSCLInteger.valueOf(0); + } + + public Generic substitute(Variable variable, Generic generic) { + if(isIdentity(variable)) return generic; + else return expressionValue(); + } + + public Generic expand() { + return expressionValue(); + } + + public Generic factorize() { + return expressionValue(); + } + + public Generic elementary() { + return expressionValue(); + } + + public Generic simplify() { + return expressionValue(); + } + + public Generic numeric() { + throw new ArithmeticException(); + } + + public boolean isConstant(Variable variable) { + return !isIdentity(variable); + } + + public int compareTo(Variable variable) { + if(this==variable) return 0; + int c=comparator.compare(this,variable); + if(c<0) return -1; + else if(c>0) return 1; + else { + TechnicalVariable v=(TechnicalVariable)variable; + c=name.compareTo(v.name); + if(c<0) return -1; + else if(c>0) return 1; + else return compareSubscript(subscript,v.subscript); + } + } + + public int compareSubscript(int c1[], int c2[]) { + if(c1.lengthc2.length) return 1; + for(int i=0;ic2[i]) return 1; + } + return 0; + } + + public String toString() { + StringBuffer buffer=new StringBuffer(); + buffer.append(name); + if(subscript.length==1) buffer.append(subscript[0]); + else for(int i=0;i0; + case 3: + return a1.compareTo(a2)!=0; + case 4: + return a1.compareTo(a2)<=0; + case 5: + return a1.compareTo(a2)>=0; + case 6: + return a1.compareTo(a2)==0; + default: + return false; + } + } + + public String toJava() { + StringBuffer buffer=new StringBuffer(); + buffer.append(parameter[0].toJava()).append(easj[operator]).append(parameter[1].toJava()); + return buffer.toString(); + } + + public void toMathML(MathML element, Object data) { + parameter[0].toMathML(element,null); + MathML e1=element.element("mo"); + e1.appendChild(element.text(easm[operator])); + element.appendChild(e1); + parameter[1].toMathML(element,null); + } + + protected Variable newinstance() { + return new Comparison(name,null,null); + } + + private static final String eass[]={"=","<=",">=","<>","<",">","~"}; + private static final String easj[]={"==","<=",">=","!=","<",">","=="}; + private static final String easm[]={"=","\u2264","\u2265","\u2260","<",">","\u2248"}; + private static final String easo[]={"eq","le","ge","ne","lt","gt","ap"}; +} diff --git a/src/misc/src/jscl/math/function/Conjugate.java b/src/misc/src/jscl/math/function/Conjugate.java new file mode 100644 index 00000000..40d52ece --- /dev/null +++ b/src/misc/src/jscl/math/function/Conjugate.java @@ -0,0 +1,132 @@ +package jscl.math.function; + +import jscl.math.Generic; +import jscl.math.JSCLInteger; +import jscl.math.JSCLVector; +import jscl.math.Matrix; +import jscl.math.NotIntegerException; +import jscl.math.NotIntegrableException; +import jscl.math.NotVariableException; +import jscl.math.NumericWrapper; +import jscl.math.Power; +import jscl.math.Variable; +import jscl.mathml.MathML; + +public class Conjugate extends Function { + public Conjugate(Generic generic) { + super("conjugate",new Generic[] {generic}); + } + + public Generic antiderivative(int n) throws NotIntegrableException { + return Constant.half.multiply(evaluate().pow(2)); + } + + public Generic derivative(int n) { + return JSCLInteger.valueOf(1); + } + + public Generic evaluate() { + try { + return parameter[0].integerValue(); + } catch (NotIntegerException e) {} + if(parameter[0] instanceof Matrix) { + return ((Matrix)parameter[0]).conjugate(); + } else if(parameter[0] instanceof JSCLVector) { + return ((JSCLVector)parameter[0]).conjugate(); + } + return expressionValue(); + } + + public Generic evalelem() { + try { + return parameter[0].integerValue(); + } catch (NotIntegerException e) {} + return expressionValue(); + } + + public Generic evalsimp() { + try { + return parameter[0].integerValue(); + } catch (NotIntegerException e) {} + if(parameter[0].signum()<0) { + return new Conjugate(parameter[0].negate()).evalsimp().negate(); + } else if(parameter[0].compareTo(Constant.i)==0) { + return Constant.i.negate(); + } + try { + Variable v=parameter[0].variableValue(); + if(v instanceof Conjugate) { + Generic g[]=((Conjugate)v).parameters(); + return g[0]; + } else if(v instanceof Exp) { + Generic g[]=((Exp)v).parameters(); + return new Exp(new Conjugate(g[0]).evalsimp()).evalsimp(); + } else if(v instanceof Log) { + Generic g[]=((Log)v).parameters(); + return new Log(new Conjugate(g[0]).evalsimp()).evalsimp(); + } + } catch (NotVariableException e) { + Generic a[]=parameter[0].sumValue(); + if(a.length>1) { + Generic s=JSCLInteger.valueOf(0); + for(int i=0;i0) return 1; + else { + Constant v=(Constant)variable; + c=name.compareTo(v.name); + if(c<0) return -1; + else if(c>0) return 1; + else { + c=ArrayComparator.comparator.compare(subscript,v.subscript); + if(c<0) return -1; + else if(c>0) return 1; + else { + if(primev.prime) return 1; + else return 0; + } + } + } + } + + public String toString() { + StringBuffer buffer=new StringBuffer(); + buffer.append(name); + for(int i=0;i1) { + Generic s=JSCLInteger.valueOf(1); + for(int i=0;i0) return 1; + else { + Function v=(Function)variable; + c=name.compareTo(v.name); + if(c<0) return -1; + else if(c>0) return 1; + else return ArrayComparator.comparator.compare(parameter,v.parameter); + } + } + + public String toString() { + StringBuffer buffer=new StringBuffer(); + buffer.append(name); + buffer.append("("); + for(int i=0;i0) c[i]=derivation[i]-1; + else throw new NotIntegrableException(); + } else c[i]=derivation[i]; + } + return new ImplicitFunction(name,parameter,c,subscript).evaluate(); + } + + public Generic derivative(int n) { + int c[]=new int[derivation.length]; + for(int i=0;i0) return 1; + else { + ImplicitFunction v=(ImplicitFunction)variable; + c=name.compareTo(v.name); + if(c<0) return -1; + else if(c>0) return 1; + else { + c=ArrayComparator.comparator.compare(subscript,v.subscript); + if(c<0) return -1; + else if(c>0) return 1; + else { + c=compareDerivation(derivation,v.derivation); + if(c<0) return -1; + else if(c>0) return 1; + else return ArrayComparator.comparator.compare(parameter,v.parameter); + } + } + } + } + + static int compareDerivation(int c1[], int c2[]) { + int n=c1.length; + for(int i=n-1;i>=0;i--) { + if(c1[i]c2[i]) return 1; + } + return 0; + } + + public String toString() { + StringBuffer buffer=new StringBuffer(); + int n=0; + for(int i=0;i0) { + Generic a[]=new Generic[d+1]; + a[0]=parameter[0].negate(); + for(int i=1;i0; + for(int i=0;i0; + for(int i=1;i0) return 1; + else { + Root v=(Root)variable; + c=ArrayComparator.comparator.compare(parameter,v.parameter); + if(c<0) return -1; + else if(c>0) return 1; + else return subscript.compareTo(v.subscript); + } + } + + public static Generic sigma(Generic parameter[], int n) { + Sigma s=new Sigma(parameter,n); + s.compute(); + return s.getValue(); + } + + public String toString() { + StringBuffer buffer=new StringBuffer(); + buffer.append(name); + buffer.append("[").append(subscript).append("]"); + buffer.append("("); + for(int i=0;i0) { + for(int i=p;i1) { +// Generic s=JSCLInteger.valueOf(0); +// for(int i=1;icomplex.imag) return 1; + else if(imag==complex.imag) { + if(realcomplex.real) return 1; + else if(real==complex.real) return 0; + else throw new ArithmeticException(); + } else throw new ArithmeticException(); + } + + public int compareTo(Numeric numeric) { + if(numeric instanceof Complex) { + return compareTo((Complex)numeric); + } else if(numeric instanceof JSCLDouble) { + return compareTo(valueof(numeric)); + } else { + return numeric.valueof(this).compareTo(numeric); + } + } + + public static Complex valueOf(double real, double imag) { + return new Complex(real,imag); + } + + public String toString() { + StringBuffer buffer=new StringBuffer(); + if(imag==0.) { + buffer.append(real); + } else { + if(real==0.); + else { + buffer.append(real); + if(imag<=0.); + else buffer.append("+"); + } + if(imag==1.); + else if(imag==-1.) buffer.append("-"); + else { + buffer.append(imag); + buffer.append("*"); + } + buffer.append("sqrt(-1)"); + } + return buffer.toString(); + } +} diff --git a/src/misc/src/jscl/math/numeric/JSCLDouble.java b/src/misc/src/jscl/math/numeric/JSCLDouble.java new file mode 100644 index 00000000..cc10d65e --- /dev/null +++ b/src/misc/src/jscl/math/numeric/JSCLDouble.java @@ -0,0 +1,174 @@ +package jscl.math.numeric; + +public final class JSCLDouble extends Numeric { + double content; + + JSCLDouble(double val) { + content=val; + } + + public JSCLDouble add(JSCLDouble dble) { + return new JSCLDouble(content+dble.content); + } + + public Numeric add(Numeric numeric) { + if(numeric instanceof JSCLDouble) { + return add((JSCLDouble)numeric); + } else { + return numeric.valueof(this).add(numeric); + } + } + + public JSCLDouble subtract(JSCLDouble dble) { + return new JSCLDouble(content-dble.content); + } + + public Numeric subtract(Numeric numeric) { + if(numeric instanceof JSCLDouble) { + return subtract((JSCLDouble)numeric); + } else { + return numeric.valueof(this).subtract(numeric); + } + } + + public JSCLDouble multiply(JSCLDouble dble) { + return new JSCLDouble(content*dble.content); + } + + public Numeric multiply(Numeric numeric) { + if(numeric instanceof JSCLDouble) { + return multiply((JSCLDouble)numeric); + } else { + return numeric.multiply(this); + } + } + + public JSCLDouble divide(JSCLDouble dble) throws ArithmeticException { + return new JSCLDouble(content/dble.content); + } + + public Numeric divide(Numeric numeric) throws ArithmeticException { + if(numeric instanceof JSCLDouble) { + return divide((JSCLDouble)numeric); + } else { + return numeric.valueof(this).divide(numeric); + } + } + + public Numeric negate() { + return new JSCLDouble(-content); + } + + public int signum() { + return content==0.?0:(content<0.?-1:1); + } + + public Numeric log() { + return new JSCLDouble(Math.log(content)); + } + + public Numeric exp() { + return new JSCLDouble(Math.exp(content)); + } + + public Numeric inverse() { + return new JSCLDouble(1./content); + } + + public Numeric pow(JSCLDouble dble) { + if(signum()<0) { + return Complex.valueOf(content,0).pow(dble); + } else { + return new JSCLDouble(Math.pow(content,dble.content)); + } + } + + public Numeric pow(Numeric numeric) { + if(numeric instanceof JSCLDouble) { + return pow((JSCLDouble)numeric); + } else { + return numeric.valueof(this).pow(numeric); + } + } + + public Numeric sqrt() { + if(signum()<0) { + return Complex.valueOf(0,1).multiply(negate().sqrt()); + } else { + return new JSCLDouble(Math.sqrt(content)); + } + } + + public Numeric nthrt(int n) { + if(signum()<0) { + return n%2==0?sqrt().nthrt(n/2):negate().nthrt(n).negate(); + } else { + return super.nthrt(n); + } + } + + public Numeric conjugate() { + return this; + } + + public Numeric acos() { + return new JSCLDouble(Math.acos(content)); + } + + public Numeric asin() { + return new JSCLDouble(Math.asin(content)); + } + + public Numeric atan() { + return new JSCLDouble(Math.atan(content)); + } + + public Numeric cos() { + return new JSCLDouble(Math.cos(content)); + } + + public Numeric sin() { + return new JSCLDouble(Math.sin(content)); + } + + public Numeric tan() { + return new JSCLDouble(Math.tan(content)); + } + + public JSCLDouble valueof(JSCLDouble dble) { + return new JSCLDouble(dble.content); + } + + public Numeric valueof(Numeric numeric) { + if(numeric instanceof JSCLDouble) { + return valueof((JSCLDouble)numeric); + } else throw new ArithmeticException(); + } + + public double doubleValue() { + return content; + } + + public int compareTo(JSCLDouble dble) { + if(contentdble.content) return 1; + else if(content==dble.content) return 0; + else throw new ArithmeticException(); + } + + public int compareTo(Numeric numeric) { + if(numeric instanceof JSCLDouble) { + return compareTo((JSCLDouble)numeric); + } else { + return numeric.valueof(this).compareTo(numeric); + } + } + + public static JSCLDouble valueOf(double val) { + return new JSCLDouble(val); + } + + public String toString() { + return new Double(content).toString(); + } +} diff --git a/src/misc/src/jscl/math/numeric/Numeric.java b/src/misc/src/jscl/math/numeric/Numeric.java new file mode 100644 index 00000000..c2044ee0 --- /dev/null +++ b/src/misc/src/jscl/math/numeric/Numeric.java @@ -0,0 +1,156 @@ +package jscl.math.numeric; + +import jscl.math.Arithmetic; + +public abstract class Numeric implements Arithmetic, Comparable { + public abstract Numeric add(Numeric numeric); + + public Numeric subtract(Numeric numeric) { + return add(numeric.negate()); + } + + public abstract Numeric multiply(Numeric numeric); + public abstract Numeric divide(Numeric numeric) throws ArithmeticException; + + public Arithmetic add(Arithmetic arithmetic) { + return add((Numeric)arithmetic); + } + + public Arithmetic subtract(Arithmetic arithmetic) { + return subtract((Numeric)arithmetic); + } + + public Arithmetic multiply(Arithmetic arithmetic) { + return multiply((Numeric)arithmetic); + } + + public Arithmetic divide(Arithmetic arithmetic) throws ArithmeticException { + return divide((Numeric)arithmetic); + } + + public Numeric pow(int exponent) { + Numeric a=JSCLDouble.valueOf(1); + for(int i=0;i0?element[0].length:0; + } + + public Numeric[][] elements() { + return element; + } + + public NumericMatrix add(NumericMatrix matrix) { + NumericMatrix m=(NumericMatrix)newinstance(); + for(int i=0;i0) return 1; + } + } + return 0; + } + + public Numeric valueof(Numeric numeric) { + if(numeric instanceof NumericMatrix || numeric instanceof NumericVector) { + throw new ArithmeticException(); + } else { + NumericMatrix m=(NumericMatrix)identity(n,p).multiply(numeric); + return newinstance(m.element); + } + } + + public Numeric[] vectors() { + NumericVector v[]=new NumericVector[n]; + for(int i=0;i1) { + Numeric a=JSCLDouble.valueOf(0); + for(int i=0;i0) return element[0][0]; + else return JSCLDouble.valueOf(0); + } + + public Numeric log() { + throw new ArithmeticException(); + } + + public Numeric exp() { + throw new ArithmeticException(); + } + + public Numeric conjugate() { + NumericMatrix m=(NumericMatrix)newinstance(); + for(int i=0;i0) return 1; + } + return 0; + } + + public Numeric valueof(Numeric numeric) { + if(numeric instanceof NumericVector || numeric instanceof NumericMatrix) { + throw new ArithmeticException(); + } else { + NumericVector v=(NumericVector)unity(n).multiply(numeric); + return newinstance(v.element); + } + } + + public Numeric magnitude2() { + return scalarProduct(this); + } + + public Numeric scalarProduct(NumericVector vector) { + Numeric a=JSCLDouble.valueOf(0); + for(int i=0;i0) return 1; + else { + Factorial v=(Factorial)variable; + return ArrayComparator.comparator.compare(parameter,v.parameter); + } + } + + public String toString() { + StringBuffer buffer=new StringBuffer(); + try { + JSCLInteger en=parameter[0].integerValue(); + buffer.append(en); + } catch (NotIntegerException e) { + try { + Variable v=parameter[0].variableValue(); + if(v instanceof Frac || v instanceof Pow) { + buffer.append(GenericVariable.valueOf(parameter[0])); + } else buffer.append(v); + } catch (NotVariableException e2) { + buffer.append(GenericVariable.valueOf(parameter[0])); + } + } + buffer.append("!"); + return buffer.toString(); + } + + public void toMathML(MathML element, Object data) { + int exponent=data instanceof Integer?((Integer)data).intValue():1; + if(exponent==1) bodyToMathML(element); + else { + MathML e1=element.element("msup"); + bodyToMathML(e1); + MathML e2=element.element("mn"); + e2.appendChild(element.text(String.valueOf(exponent))); + e1.appendChild(e2); + element.appendChild(e1); + } + } + + void bodyToMathML(MathML element) { + MathML e1=element.element("mrow"); + try { + JSCLInteger en=parameter[0].integerValue(); + en.toMathML(e1,null); + } catch (NotIntegerException e) { + try { + Variable v=parameter[0].variableValue(); + if(v instanceof Pow) { + GenericVariable.valueOf(parameter[0]).toMathML(e1,null); + } else v.toMathML(e1,null); + } catch (NotVariableException e2) { + GenericVariable.valueOf(parameter[0]).toMathML(e1,null); + } + } + MathML e2=element.element("mo"); + e2.appendChild(element.text("!")); + e1.appendChild(e2); + element.appendChild(e1); + } + + protected Variable newinstance() { + return new Factorial(null); + } +} diff --git a/src/misc/src/jscl/math/operator/Groebner.java b/src/misc/src/jscl/math/operator/Groebner.java new file mode 100644 index 00000000..52d9e427 --- /dev/null +++ b/src/misc/src/jscl/math/operator/Groebner.java @@ -0,0 +1,138 @@ +package jscl.math.operator; + +import jscl.math.Generic; +import jscl.math.GenericVariable; +import jscl.math.JSCLInteger; +import jscl.math.JSCLVector; +import jscl.math.Variable; +import jscl.math.function.Constant; +import jscl.math.function.ImplicitFunction; +import jscl.math.polynomial.Basis; +import jscl.math.polynomial.Monomial; +import jscl.math.polynomial.Ordering; +import jscl.math.polynomial.Polynomial; +import jscl.mathml.MathML; + +public class Groebner extends Operator { + public Groebner(Generic generic, Generic variable, Generic ordering, Generic modulo) { + super("groebner",new Generic[] {generic,variable,ordering,modulo}); + } + + public Generic compute() { + Generic generic[]=((JSCLVector)parameter[0]).elements(); + Variable variable[]=variables(parameter[1]); + Ordering ord=ordering(parameter[2]); + int m=parameter[3].integerValue().intValue(); + return new PolynomialVector(Basis.compute(generic,variable,ord,m)); + } + + public Operator transmute() { + Generic p[]=new Generic[] {GenericVariable.content(parameter[0]),GenericVariable.content(parameter[1])}; + if(p[0] instanceof JSCLVector && p[1] instanceof JSCLVector) { + Generic generic[]=((JSCLVector)p[0]).elements(); + Variable variable[]=variables(p[1]); + Ordering ord=ordering(parameter[2]); + int m=parameter[3].integerValue().intValue(); + return new Groebner(new PolynomialVector(new Basis(generic,Polynomial.factory(variable,ord,m))),p[1],parameter[2],parameter[3]); + } + return this; + } + + static Ordering ordering(Generic generic) { + Variable v=generic.variableValue(); + if(v.compareTo(new Constant("lex"))==0) return Monomial.lexicographic; + else if(v.compareTo(new Constant("tdl"))==0) return Monomial.totalDegreeLexicographic; + else if(v.compareTo(new Constant("drl"))==0) return Monomial.degreeReverseLexicographic; + else if(v instanceof ImplicitFunction) { + Generic g[]=((ImplicitFunction)v).parameters(); + int k=g[0].integerValue().intValue(); + if(v.compareTo(new ImplicitFunction("elim",new Generic[] {JSCLInteger.valueOf(k)},new int[] {0},new Generic[] {}))==0) return Monomial.kthElimination(k); + } + throw new ArithmeticException(); + } + + public String toString() { + StringBuffer buffer=new StringBuffer(); + int n=4; + if(parameter[3].signum()==0) { + n=3; + if(ordering(parameter[2])==Monomial.lexicographic) n=2; + } + buffer.append(name); + buffer.append("("); + for(int i=0;i0?generic:new Generic[] {JSCLInteger.valueOf(0)}); + this.basis=basis; + } + + public String toString() { + StringBuffer buffer=new StringBuffer(); + buffer.append("{"); + for(int i=0;i0) e5.appendChild(element.text("+")); + e4.appendChild(e5); + e3.appendChild(e4); + } + e2.appendChild(e3); + e1.appendChild(e2); + parameter[0].toMathML(e1,null); + element.appendChild(e1); + } + + protected Variable newinstance() { + return new Limit(null,null,null,null); + } +} diff --git a/src/misc/src/jscl/math/operator/Modulo.java b/src/misc/src/jscl/math/operator/Modulo.java new file mode 100644 index 00000000..2325f649 --- /dev/null +++ b/src/misc/src/jscl/math/operator/Modulo.java @@ -0,0 +1,25 @@ +package jscl.math.operator; + +import jscl.math.Generic; +import jscl.math.JSCLInteger; +import jscl.math.NotIntegerException; +import jscl.math.Variable; + +public class Modulo extends Operator { + public Modulo(Generic expression1, Generic expression2) { + super("mod",new Generic[] {expression1,expression2}); + } + + public Generic compute() { + try { + JSCLInteger en=parameter[0].integerValue(); + JSCLInteger en2=parameter[1].integerValue(); + return en.mod(en2); + } catch (NotIntegerException e) {} + return parameter[0].remainder(parameter[1]); + } + + protected Variable newinstance() { + return new Modulo(null,null); + } +} diff --git a/src/misc/src/jscl/math/operator/Operator.java b/src/misc/src/jscl/math/operator/Operator.java new file mode 100644 index 00000000..b36d2e75 --- /dev/null +++ b/src/misc/src/jscl/math/operator/Operator.java @@ -0,0 +1,140 @@ +package jscl.math.operator; + +import jscl.math.Generic; +import jscl.math.JSCLInteger; +import jscl.math.JSCLVector; +import jscl.math.NotIntegrableException; +import jscl.math.NotVariableException; +import jscl.math.Variable; +import jscl.mathml.MathML; +import jscl.util.ArrayComparator; + +public abstract class Operator extends Variable { + protected Generic parameter[]; + + public Operator(String name, Generic parameter[]) { + super(name); + this.parameter=parameter; + } + + public Generic[] parameters() { + return parameter; + } + + public abstract Generic compute(); + + public Generic antiderivative(Variable variable) throws NotIntegrableException { + return null; + } + + public Generic derivative(Variable variable) { + if(isIdentity(variable)) return JSCLInteger.valueOf(1); + else return JSCLInteger.valueOf(0); + } + + public Generic substitute(Variable variable, Generic generic) { + Operator v=(Operator)newinstance(); + for(int i=0;i0) return 1; + else { + Operator v=(Operator)variable; + c=name.compareTo(v.name); + if(c<0) return -1; + else if(c>0) return 1; + else return ArrayComparator.comparator.compare(parameter,v.parameter); + } + } + + protected static Variable[] variables(Generic generic) throws NotVariableException { + Generic element[]=((JSCLVector)generic).elements(); + Variable variable[]=new Variable[element.length]; + for(int i=0;i0?a:new Generic[] {JSCLInteger.valueOf(0)}); + } catch (NotIntegerException e) {} + return expressionValue(); + } + + protected Variable newinstance() { + return new PrimitiveRoots(null); + } +} diff --git a/src/misc/src/jscl/math/operator/product/ComplexProduct.java b/src/misc/src/jscl/math/operator/product/ComplexProduct.java new file mode 100644 index 00000000..ed0a47ec --- /dev/null +++ b/src/misc/src/jscl/math/operator/product/ComplexProduct.java @@ -0,0 +1,31 @@ +package jscl.math.operator.product; + +import jscl.math.Generic; +import jscl.math.JSCLVector; +import jscl.math.Variable; +import jscl.math.operator.VectorOperator; +import jscl.mathml.MathML; + +public class ComplexProduct extends VectorOperator { + public ComplexProduct(Generic vector1, Generic vector2) { + super("complex",new Generic[] {vector1,vector2}); + } + + public Generic compute() { + if(parameter[0] instanceof JSCLVector && parameter[1] instanceof JSCLVector) { + JSCLVector v1=(JSCLVector)parameter[0]; + JSCLVector v2=(JSCLVector)parameter[1]; + return v1.complexProduct(v2); + } + return expressionValue(); + } + + protected void bodyToMathML(MathML element) { + parameter[0].toMathML(element,null); + parameter[1].toMathML(element,null); + } + + protected Variable newinstance() { + return new ComplexProduct(null,null); + } +} diff --git a/src/misc/src/jscl/math/operator/product/GeometricProduct.java b/src/misc/src/jscl/math/operator/product/GeometricProduct.java new file mode 100644 index 00000000..f5acaea6 --- /dev/null +++ b/src/misc/src/jscl/math/operator/product/GeometricProduct.java @@ -0,0 +1,59 @@ +package jscl.math.operator.product; + +import jscl.math.Generic; +import jscl.math.JSCLInteger; +import jscl.math.JSCLVector; +import jscl.math.Variable; +import jscl.math.function.ImplicitFunction; +import jscl.math.operator.VectorOperator; +import jscl.mathml.MathML; + +public class GeometricProduct extends VectorOperator { + public GeometricProduct(Generic vector1, Generic vector2, Generic algebra) { + super("geometric",new Generic[] {vector1,vector2,algebra}); + } + + public Generic compute() { + int algebra[]=algebra(parameter[2]); + if(parameter[0] instanceof JSCLVector && parameter[1] instanceof JSCLVector) { + JSCLVector v1=(JSCLVector)parameter[0]; + JSCLVector v2=(JSCLVector)parameter[1]; + return v1.geometricProduct(v2,algebra); + } + return expressionValue(); + } + + public static int[] algebra(Generic generic) { + if(generic.signum()==0) return null; + Variable v=generic.variableValue(); + if(v instanceof ImplicitFunction) { + Generic g[]=((ImplicitFunction)v).parameters(); + int p=g[0].integerValue().intValue(); + int q=g[1].integerValue().intValue(); + if(v.compareTo(new ImplicitFunction("cl",new Generic[] {JSCLInteger.valueOf(p),JSCLInteger.valueOf(q)},new int[] {0,0},new Generic[] {}))==0) return new int[] {p,q}; + } + throw new ArithmeticException(); + } + + public String toString() { + StringBuffer buffer=new StringBuffer(); + int n=3; + if(parameter[2].signum()==0) n=2; + buffer.append(name); + buffer.append("("); + for(int i=0;i0:index0?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; + } + + public Polynomial multiply(Polynomial polynomial) { + Polynomial p=valueof(JSCLInteger.valueOf(0)); + for(int i=0;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;i0?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;i0?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;i0?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;i0:index0?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) { + Generic a=getCoef(i1); + --i; + p.monomial[i]=m1; + p.setCoef(i,a); + m1=i1>0?monomial[--i1]:null; + } else if(c>0) { + Generic a=q.getCoef(i2).negate(); + --i; + p.monomial[i]=m2; + p.setCoef(i,a); + m2=i2>0?q.monomial[--i2]:null; + } else { + Generic a=getCoef(i1).subtract(q.getCoef(i2)); + if(a.signum()!=0) { + --i; + p.monomial[i]=m1; + p.setCoef(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; + if(generic.compareTo(JSCLInteger.valueOf(1))==0) return subtract(polynomial); + ArrayPolynomialGeneric q=(ArrayPolynomialGeneric)polynomial; + ArrayPolynomialGeneric p=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) { + Generic a=getCoef(i1); + --i; + p.monomial[i]=m1; + p.setCoef(i,a); + m1=i1>0?monomial[--i1]:null; + } else if(c>0) { + Generic a=q.getCoef(i2).multiply(generic).negate(); + --i; + p.monomial[i]=m2; + p.setCoef(i,a); + m2=i2>0?q.monomial[--i2]:null; + } else { + Generic a=getCoef(i1).subtract(q.getCoef(i2).multiply(generic)); + if(a.signum()!=0) { + --i; + p.monomial[i]=m1; + p.setCoef(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); + ArrayPolynomialGeneric q=(ArrayPolynomialGeneric)polynomial; + ArrayPolynomialGeneric p=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) { + Generic a=getCoef(i1); + --i; + p.monomial[i]=m1; + p.setCoef(i,a); + m1=i1>0?this.monomial[--i1]:null; + } else if(c>0) { + Generic a=q.getCoef(i2).multiply(generic).negate(); + --i; + p.monomial[i]=m2; + p.setCoef(i,a); + m2=i2>0?q.monomial[--i2].multiply(monomial):null; + } else { + Generic a=getCoef(i1).subtract(q.getCoef(i2).multiply(generic)); + if(a.signum()!=0) { + --i; + p.monomial[i]=m1; + p.setCoef(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(Polynomial polynomial) { + Polynomial p=newinstance(0); + for(int i=0;i=0;i--) a=a.gcd(getCoef(i)); + return a.signum()==signum()?a:a.negate(); + } + + public Monomial monomialGcd() { + Monomial m=monomial(tail()); + for(int i=0;i0?term(size-1):null; + } + + public Term tail() { + return size>0?term(0):null; + } + + protected Generic getCoef(int n) { + return coef[n]; + } + + protected void setCoef(int n, Generic generic) { + coef[n]=generic; + } + + public Generic genericValue() { + Generic s=JSCLInteger.valueOf(0); + for(int i=0;i0?a.multiply(Expression.valueOf(m.literalValue())):a); + } + return s; + } + + public Generic[] elements() { + Generic a[]=new Generic[size]; + for(int i=0;i0) return 1; + else { + c=getCoef(i1).compareTo(q.getCoef(i2)); + if(c<0) return -1; + else if(c>0) return 1; + m1=i1==0?null:monomial[--i1]; + m2=i2==0?null:q.monomial[--i2]; + } + } + return 0; + } + + void init(Polynomial polynomial) { + ArrayPolynomialGeneric q=(ArrayPolynomialGeneric)polynomial; + init(q.size); + System.arraycopy(q.monomial,0,monomial,0,size); + for(int i=0;i0?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;i0?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) { + BigInteger a=coef[i1]; + --i; + p.monomial[i]=m1; + p.coef[i]=a; + m1=i1>0?monomial[--i1]:null; + } else if(c>0) { + BigInteger a=q.coef[i2].negate(); + --i; + p.monomial[i]=m2; + p.coef[i]=a; + m2=i2>0?q.monomial[--i2]:null; + } else { + BigInteger a=coef[i1].subtract(q.coef[i2]); + if(a.signum()!=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; + BigInteger g=generic.integerValue().content(); + if(g.compareTo(BigInteger.valueOf(1))==0) return subtract(polynomial); + ArrayPolynomialInteger q=(ArrayPolynomialInteger)polynomial; + ArrayPolynomialInteger p=(ArrayPolynomialInteger)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) { + BigInteger a=coef[i1]; + --i; + p.monomial[i]=m1; + p.coef[i]=a; + m1=i1>0?monomial[--i1]:null; + } else if(c>0) { + BigInteger a=q.coef[i2].multiply(g).negate(); + --i; + p.monomial[i]=m2; + p.coef[i]=a; + m2=i2>0?q.monomial[--i2]:null; + } else { + BigInteger a=coef[i1].subtract(q.coef[i2].multiply(g)); + if(a.signum()!=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); + BigInteger g=generic.integerValue().content(); + ArrayPolynomialInteger q=(ArrayPolynomialInteger)polynomial; + ArrayPolynomialInteger p=(ArrayPolynomialInteger)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) { + BigInteger a=coef[i1]; + --i; + p.monomial[i]=m1; + p.coef[i]=a; + m1=i1>0?this.monomial[--i1]:null; + } else if(c>0) { + BigInteger a=q.coef[i2].multiply(g).negate(); + --i; + p.monomial[i]=m2; + p.coef[i]=a; + m2=i2>0?q.monomial[--i2].multiply(monomial):null; + } else { + BigInteger a=coef[i1].subtract(q.coef[i2].multiply(g)); + if(a.signum()!=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)); + BigInteger g=generic.integerValue().content(); + if(g.compareTo(BigInteger.valueOf(1))==0) return this; + ArrayPolynomialInteger p=(ArrayPolynomialInteger)newinstance(size); + for(int i=0;i=0;i--) if((a=a.gcd(coef[i])).compareTo(BigInteger.valueOf(1))==0) break; + return new JSCLInteger(a.signum()==signum()?a:a.negate()); + } + + protected Generic coefficient(Generic generic) { + return coefFactory.valueof(generic); + } + + protected Generic getCoef(int n) { + return new JSCLInteger(coef[n]); + } + + protected void setCoef(int n, Generic generic) { + coef[n]=generic.integerValue().content(); + } + + protected ArrayPolynomialGeneric newinstance(int n) { + return new ArrayPolynomialInteger(n,monomialFactory); + } +} diff --git a/src/misc/src/jscl/math/polynomial/ArrayPolynomialModular.java b/src/misc/src/jscl/math/polynomial/ArrayPolynomialModular.java new file mode 100644 index 00000000..e4ee5d62 --- /dev/null +++ b/src/misc/src/jscl/math/polynomial/ArrayPolynomialModular.java @@ -0,0 +1,207 @@ +package jscl.math.polynomial; + +import jscl.math.Generic; +import jscl.math.JSCLInteger; +import jscl.math.ModularInteger; + +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(size0?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;i0,(flags&DEFINING_EQS)>0); + } + + static Basis compute(Generic generic[], Variable unknown[], Ordering ordering, int modulo, int flags, boolean degree, boolean defining) { + if(degree) return compute(compute(generic,unknown,Monomial.degreeReverseLexicographic,modulo,flags,false,defining).elements(),unknown,ordering,modulo,flags,false,defining); + return Standard.compute(new Basis(defining?augment(defining(unknown,modulo),generic):generic,Polynomial.factory(unknown,ordering,modulo,flags)),flags); + } + + public Basis valueof(Generic generic[]) { + return new Basis(generic,factory); + } + + public Basis modulo(int modulo) { + return new Basis(element,Polynomial.factory(factory,modulo)); + } + + public static Generic[] defining(Variable unknown[], int modulo) { + Generic a[]=new Generic[unknown.length]; + for(int i=0;i0 && generic[0].compareTo(JSCLInteger.valueOf(1))==0); + } + + public static Generic[] augment(Generic element[], Generic generic[]) { + return (Generic[])ArrayUtils.concat(element,generic,new Generic[element.length+generic.length]); + } + + public static Variable[] augmentUnknown(Variable unknown[], Generic generic[]) { + Variable va[]=Expression.variables(generic); + List l=new ArrayList(); + for(int i=0;i>log2p)+1,unknown,ordering); + } + + BooleanMonomial(int length, Variable unknown[], Ordering ordering) { + super(length,unknown,ordering); + } + + public Monomial multiply(Monomial monomial) { + Monomial m=newinstance(); + for(int i=0;i>log2p; + int r=(i&pmask)<>r)&nmask; + int b=(monomial.element[q]>>r)&nmask; + int c=a+b; + if(c>nmask) throw new ArithmeticException(); + m.element[q]|=c<>log2p; + int r=(i&pmask)<>r)&nmask; + int b=(monomial.element[q]>>r)&nmask; + if(a>log2p; + int r=(i&pmask)<>r)&nmask; + int b=(monomial.element[q]>>r)&nmask; + int c=a-b; + if(c<0) throw new NotDivisibleException(); + m.element[q]|=c<>log2p; + int r=(i&pmask)<>r)&nmask; + int b=(monomial.element[q]>>r)&nmask; + int c=Math.min(a,b); + m.element[q]|=c<>log2p; + int r=(i&pmask)<>r)&nmask; + int b=(monomial.element[q]>>r)&nmask; + int c=Math.max(a,b); + m.element[q]|=c<>log2p; + int r=(n&pmask)<>r)&nmask; + } + + void put(int n, int integer) { + if(reverse()) n=unknown.length-1-n; + int q=n>>log2p; + int r=(n&pmask)<>r)&nmask; + int c=a+integer; + if(c>nmask) throw new ArithmeticException(); + element[q]|=c<>log2p; + int r=(i&pmask)<>r)&nmask; + int b=(monomial.element[q]>>r)&nmask; + int c=a+b; + if(c>1) c=1; + m.element[q]|=c<0) { + t=u; + n=i; + } else if(ordering.compare(t.monomial(),u.monomial())==0) { + t=behead(t,n,i); + n=i; + } + } + if(t==null || t.coef().signum()!=0) { + term=t; + return; + } + } + } + + public boolean hasNext() { + return term!=null; + } + + public Object next() { + Term t=term; + seek(); + return t; + } + + public void remove() { + throw new UnsupportedOperationException(); + } + } + + Term behead(Term t, int n, int i) { + Monomial m=t.monomial(); + Polynomial p=factory.valueof(m).multiply(t.coef()); + content[n]=content[n].subtract(p); + content[i]=content[i].add(p); + return new Term(m,content[i].coefficient(m)); + } + + void canonicalize() { + Polynomial s=factory.valueof(JSCLInteger.valueOf(0)); + int sugar=0; + for(int i=0;i3;n>>=2) i++; + return i; + } + + Polynomial polynomial() { + if(canonicalized) return content[size-1]; + else throw new UnsupportedOperationException(); + } + + void set(Polynomial polynomial) { + content[size-1]=polynomial; + } + + public Polynomial subtract(Polynomial polynomial) { + if(mutable) { + Polynomial q=((GeoBucket)polynomial).polynomial(); + int n=log(q.size()); + if(n>=size) resize(n+1); + Polynomial p=content[n]; + Polynomial s=(p==null?factory.valueof(JSCLInteger.valueOf(0)):p).subtract(q); + content[n]=null; + while(n=size) resize(n+1); + p=content[n]; + if(p!=null) s=p.add(s); + content[n]=null; + } + content[n]=s; + canonicalized=false; + normalized=false; + return this; + } else return copy().subtract(polynomial); + } + + public Polynomial multiplyAndSubtract(Generic generic, Polynomial polynomial) { + if(mutable) { + Polynomial q=((GeoBucket)polynomial).polynomial(); + int n=log(q.size()); + if(n>=size) resize(n+1); + Polynomial p=content[n]; + Polynomial s=(p==null?factory.valueof(JSCLInteger.valueOf(0)):p).multiplyAndSubtract(generic,q); + content[n]=null; + while(n=size) resize(n+1); + p=content[n]; + if(p!=null) s=p.add(s); + content[n]=null; + } + content[n]=s; + canonicalized=false; + normalized=false; + return this; + } else return copy().multiplyAndSubtract(generic,polynomial); + } + + public Polynomial multiplyAndSubtract(Monomial monomial, Generic generic, Polynomial polynomial) { + if(mutable) { + Polynomial q=((GeoBucket)polynomial).polynomial(); + int n=log(q.size()); + if(n>=size) resize(n+1); + Polynomial p=content[n]; + Polynomial s=(p==null?factory.valueof(JSCLInteger.valueOf(0)):p).multiplyAndSubtract(monomial,generic,q); + content[n]=null; + while(n=size) resize(n+1); + p=content[n]; + if(p!=null) s=p.add(s); + content[n]=null; + } + content[n]=s; + canonicalized=false; + normalized=false; + return this; + } else return copy().multiplyAndSubtract(monomial,generic,polynomial); + } + + public Polynomial multiply(Generic generic) { + if(mutable) { + if(canonicalized) set(polynomial().multiply(generic)); + else for(int i=0;i0) { + if(t1!=null) it1.next(); + it1.add(t2.negate()); + } else { + Term t=t1.subtract(t2); + if(t.signum()==0) it1.remove(); + else it1.set(t); + } + t1=it1.hasPrevious()?(Term)it1.previous():null; + t2=it2.hasPrevious()?(Term)it2.previous():null; + } + } + degree=degree(this); + sugar=Math.max(sugar,q.sugar); + normalized=false; + return this; + } else return copy().subtract(polynomial); + } + + public Polynomial multiplyAndSubtract(Generic generic, Polynomial polynomial) { + if(generic.signum()==0) return this; + if(generic.compareTo(JSCLInteger.valueOf(1))==0) return subtract(polynomial); + if(mutable) { + ListPolynomial q=(ListPolynomial)polynomial; + ListIterator it1=content.listIterator(content.size()); + ListIterator it2=q.content.listIterator(q.content.size()); + Term t1=it1.hasPrevious()?(Term)it1.previous():null; + Term t2=it2.hasPrevious()?((Term)it2.previous()).multiply(generic):null; + while(t2!=null) { + int c=t1==null?1:(t2==null?-1:-ordering.compare(t1.monomial(),t2.monomial())); + if(c<0) { + t1=it1.hasPrevious()?(Term)it1.previous():null; + } else { + if(c>0) { + if(t1!=null) it1.next(); + it1.add(t2.negate()); + } else { + Term t=t1.subtract(t2); + if(t.signum()==0) it1.remove(); + else it1.set(t); + } + t1=it1.hasPrevious()?(Term)it1.previous():null; + t2=it2.hasPrevious()?((Term)it2.previous()).multiply(generic):null; + } + } + degree=degree(this); + sugar=Math.max(sugar,q.sugar); + normalized=false; + return this; + } else return copy().multiplyAndSubtract(generic,polynomial); + } + + 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); + if(mutable) { + ListPolynomial q=(ListPolynomial)polynomial; + ListIterator it1=content.listIterator(content.size()); + ListIterator it2=q.content.listIterator(q.content.size()); + Term t1=it1.hasPrevious()?(Term)it1.previous():null; + Term t2=it2.hasPrevious()?((Term)it2.previous()).multiply(monomial,generic):null; + while(t2!=null) { + int c=t1==null?1:(t2==null?-1:-ordering.compare(t1.monomial(),t2.monomial())); + if(c<0) { + t1=it1.hasPrevious()?(Term)it1.previous():null; + } else { + if(c>0) { + if(t1!=null) it1.next(); + it1.add(t2.negate()); + } else { + Term t=t1.subtract(t2); + if(t.signum()==0) it1.remove(); + else it1.set(t); + } + t1=it1.hasPrevious()?(Term)it1.previous():null; + t2=it2.hasPrevious()?((Term)it2.previous()).multiply(monomial,generic):null; + } + } + degree=degree(this); + sugar=Math.max(sugar,q.sugar+monomial.degree()); + normalized=false; + return this; + } else return copy().multiplyAndSubtract(monomial,generic,polynomial); + } + + public Polynomial multiply(Generic generic) { + if(generic.signum()==0) return valueof(JSCLInteger.valueOf(0)); + if(generic.compareTo(JSCLInteger.valueOf(1))==0) return this; + if(mutable) { + ListIterator it=content.listIterator(); + while(it.hasNext()) it.set(((Term)it.next()).multiply(generic)); + normalized=false; + return this; + } else return copy().multiply(generic); + } + + public Polynomial multiply(Monomial monomial) { + if(defined) throw new UnsupportedOperationException(); + if(monomial.degree()==0) return this; + if(mutable) { + ListIterator it=content.listIterator(); + while(it.hasNext()) it.set(((Term)it.next()).multiply(monomial)); + degree+=monomial.degree(); + sugar+=monomial.degree(); + return this; + } else return copy().multiply(monomial); + } + + public Polynomial divide(Generic generic) throws ArithmeticException { + if(generic.compareTo(JSCLInteger.valueOf(1))==0) return this; + if(mutable) { + ListIterator it=content.listIterator(); + while(it.hasNext()) it.set(((Term)it.next()).divide(generic)); + normalized=false; + return this; + } else return copy().divide(generic); + } + + public Polynomial divide(Monomial monomial) throws ArithmeticException { + if(monomial.degree()==0) return this; + if(mutable) { + ListIterator it=content.listIterator(); + while(it.hasNext()) it.set(((Term)it.next()).divide(monomial)); + degree-=monomial.degree(); + sugar-=monomial.degree(); + return this; + } else return copy().divide(monomial); + } + + public Polynomial gcd(Polynomial polynomial) { + throw new UnsupportedOperationException(); + } + + public int degree() { + return degree; + } + + public Polynomial valueof(Polynomial polynomial) { + ListPolynomial p=newinstance(0); + p.init(polynomial); + return p; + } + + public Polynomial valueof(Generic generic) { + ListPolynomial p=newinstance(0); + p.init(generic); + return p; + } + + public Polynomial valueof(Monomial monomial) { + ListPolynomial p=newinstance(0); + p.init(monomial); + return p; + } + + public Polynomial freeze() { + mutable=false; + return this; + } + + public Term head() { + int size=content.size(); + return size>0?(Term)content.get(size-1):null; + } + + public Term tail() { + int size=content.size(); + return size>0?(Term)content.get(0):null; + } + + void init(Polynomial polynomial) { + ListPolynomial q=(ListPolynomial)polynomial; + content.addAll(q.content); + degree=q.degree; + sugar=q.sugar; + } + + void init(Expression expression) { + Map map=new TreeMap(ordering); + int n=expression.size(); + for(int i=0;i0?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); + } + int sugar=0; + Iterator it=map.entrySet().iterator(); + while(it.hasNext()) { + Map.Entry e=(Map.Entry)it.next(); + Monomial m=(Monomial)e.getKey(); + Generic a=(Generic)e.getValue(); + content.add(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) { + content.add(new Term(monomial(Literal.valueOf()),a)); + } + degree=0; + sugar=0; + } + } + + void init(Monomial monomial) { + content.add(new Term(monomial,coefficient(JSCLInteger.valueOf(1)))); + degree=monomial.degree(); + sugar=monomial.degree(); + } + + protected ListPolynomial newinstance(int n) { + return new ListPolynomial(monomialFactory,coefFactory); + } +} diff --git a/src/misc/src/jscl/math/polynomial/Monomial.java b/src/misc/src/jscl/math/polynomial/Monomial.java new file mode 100644 index 00000000..6658ab59 --- /dev/null +++ b/src/misc/src/jscl/math/polynomial/Monomial.java @@ -0,0 +1,406 @@ +package jscl.math.polynomial; + +import java.util.Iterator; +import jscl.math.Literal; +import jscl.math.NotDivisibleException; +import jscl.math.Variable; +import jscl.math.function.Frac; +import jscl.math.function.Pow; +import jscl.mathml.MathML; + +public class Monomial implements Comparable { + public static final Ordering lexicographic=Lexicographic.ordering; + public static final Ordering totalDegreeLexicographic=TotalDegreeLexicographic.ordering; + public static final Ordering degreeReverseLexicographic=DegreeReverseLexicographic.ordering; + public static final Ordering iteratorOrdering=totalDegreeLexicographic; + final Variable unknown[]; + final Ordering ordering; + final int element[]; + int degree; + + Monomial(Variable unknown[], Ordering ordering) { + this(unknown.length,unknown,ordering); + } + + Monomial(int length, Variable unknown[], Ordering ordering) { + this.unknown=unknown; + this.ordering=ordering; + element=new int[length]; + } + + public static Ordering kthElimination(int k) { + return new KthElimination(k,1); + } + + public Variable[] unknown() { + return unknown; + } + + public Ordering ordering() { + return ordering; + } + + public Monomial multiply(Monomial monomial) { + Monomial m=newinstance(); + for(int i=0;i0) { + if(b) buffer.append("*"); + else b=true; + Variable v=unknown[i]; + if(c==1) buffer.append(v); + else { + if(v instanceof Frac || v instanceof Pow) { + buffer.append("(").append(v).append(")"); + } else buffer.append(v); + buffer.append("^").append(c); + } + } + } + return buffer.toString(); + } + + public void toMathML(MathML element, Object data) { + if(degree==0) { + MathML e1=element.element("mn"); + e1.appendChild(element.text("1")); + element.appendChild(e1); + } + for(int i=0;i0) { + unknown[i].toMathML(element,new Integer(c)); + } + } + } + + protected Monomial newinstance() { + return new Monomial(element.length,unknown,ordering); + } +} + +class MonomialIterator implements Iterator { + static final Ordering ordering=Monomial.iteratorOrdering; + Monomial monomial; + Monomial current; + boolean carry; + + MonomialIterator(Monomial beginning, Monomial monomial) { + this.monomial=monomial; + current=monomial.valueof(beginning); + if(ordering.compare(current,monomial)>0) carry=true; + } + + public boolean hasNext() { + return !carry; + } + + public Object next() { + Monomial m=monomial.valueof(current); + if(ordering.compare(current,monomial)<0) increment(); + else carry=true; + return m; + } + + void increment() { + int s=0; + int n=0; + while(n0) { + n--; + if(current.element[n]>monomial.element[n]) break; + } + int p=n; + while(n>0) { + n--; + current.element[p]+=current.element[n]; + current.element[n]=0; + } + if(pmonomial.element[p]) increment(); + } + + void increment() { + int s=0; + int n=0; + while(n=0;i--) { + if(c1[i]c2[i]) return 1; + } + return 0; + } +} + +class TotalDegreeLexicographic extends Lexicographic implements DegreeOrdering { + public static final Ordering ordering=new TotalDegreeLexicographic(); + + TotalDegreeLexicographic() {} + + public int compare(Monomial m1, Monomial m2) { + if(m1.degreem2.degree) return 1; + else return super.compare(m1,m2); + } +} + +class DegreeReverseLexicographic extends Ordering implements DegreeOrdering { + public static final Ordering ordering=new DegreeReverseLexicographic(); + + DegreeReverseLexicographic() {} + + public int compare(Monomial m1, Monomial m2) { + if(m1.degreem2.degree) return 1; + else { + int c1[]=m1.element; + int c2[]=m2.element; + int n=c1.length; + for(int i=0;ic2[i]) return -1; + else if(c1[i]=k;i--) { + if(c1[i]c2[i]) return 1; + } + return DegreeReverseLexicographic.ordering.compare(m1,m2); + } +} diff --git a/src/misc/src/jscl/math/polynomial/NestedPolynomial.java b/src/misc/src/jscl/math/polynomial/NestedPolynomial.java new file mode 100644 index 00000000..8ac7df8f --- /dev/null +++ b/src/misc/src/jscl/math/polynomial/NestedPolynomial.java @@ -0,0 +1,225 @@ +package jscl.math.polynomial; + +import jscl.math.Expression; +import jscl.math.Generic; +import jscl.math.JSCLInteger; +import jscl.math.NotExpressionException; +import jscl.math.NotIntegerException; +import jscl.math.NotIntegrableException; +import jscl.math.NotPowerException; +import jscl.math.NotProductException; +import jscl.math.NotVariableException; +import jscl.math.Power; +import jscl.math.Variable; +import jscl.mathml.MathML; + +class NestedPolynomial extends UnivariatePolynomial { + NestedPolynomial(Variable variable[]) { + this(variable[0],PolynomialWrapper.factory(variable)); + } + + NestedPolynomial(Variable variable, Generic coefFactory) { + super(variable,coefFactory); + } + + protected UnivariatePolynomial newinstance() { + return new NestedPolynomial(variable,coefFactory); + } +} + +final class PolynomialWrapper extends Generic { + final Polynomial content; + + PolynomialWrapper(Polynomial polynomial) { + content=polynomial; + } + + Polynomial content() { + return content; + } + + public PolynomialWrapper add(PolynomialWrapper wrapper) { + return new PolynomialWrapper(content.add(wrapper.content)); + } + + public Generic add(Generic generic) { + if(generic instanceof PolynomialWrapper) { + return add((PolynomialWrapper)generic); + } else { + return add(valueof(generic)); + } + } + + public PolynomialWrapper subtract(PolynomialWrapper wrapper) { + return new PolynomialWrapper(content.subtract(wrapper.content)); + } + + public Generic subtract(Generic generic) { + if(generic instanceof PolynomialWrapper) { + return subtract((PolynomialWrapper)generic); + } else { + return subtract(valueof(generic)); + } + } + + public PolynomialWrapper multiply(PolynomialWrapper wrapper) { + return new PolynomialWrapper(content.multiply(wrapper.content)); + } + + public Generic multiply(Generic generic) { + if(generic instanceof PolynomialWrapper) { + return multiply((PolynomialWrapper)generic); + } else { + return multiply(valueof(generic)); + } + } + + public PolynomialWrapper divide(PolynomialWrapper wrapper) throws ArithmeticException { + return new PolynomialWrapper(content.divide(wrapper.content)); + } + + public Generic divide(Generic generic) throws ArithmeticException { + if(generic instanceof PolynomialWrapper) { + return divide((PolynomialWrapper)generic); + } else { + return divide(valueof(generic)); + } + } + + public PolynomialWrapper gcd(PolynomialWrapper wrapper) { + return new PolynomialWrapper(content.gcd(wrapper.content)); + } + + public Generic gcd(Generic generic) { + if(generic instanceof PolynomialWrapper) { + return gcd((PolynomialWrapper)generic); + } else { + return gcd(valueof(generic)); + } + } + + public Generic gcd() { + return content.gcd(); + } + + public Generic negate() { + return new PolynomialWrapper(content.negate()); + } + + public int signum() { + return content.signum(); + } + + public int degree() { + return content.degree(); + } + + public Generic antiderivative(Variable variable) throws NotIntegrableException { + return null; + } + + public Generic derivative(Variable variable) { + return null; + } + + public Generic substitute(Variable variable, Generic generic) { + return null; + } + + public Generic expand() { + return null; + } + + public Generic factorize() { + return null; + } + + public Generic elementary() { + return null; + } + + public Generic simplify() { + return null; + } + + public Generic numeric() { + return null; + } + + public Generic valueof(Generic generic) { + if(generic instanceof PolynomialWrapper) { + return new PolynomialWrapper(content.valueof(((PolynomialWrapper)generic).content)); + } else { + return new PolynomialWrapper(content.valueof(generic)); + } + } + + public Generic[] sumValue() { + return null; + } + + public Generic[] productValue() throws NotProductException { + return null; + } + + public Power powerValue() throws NotPowerException { + return null; + } + + public Expression expressionValue() throws NotExpressionException { + return content.genericValue().expressionValue(); + } + + public JSCLInteger integerValue() throws NotIntegerException { + throw new NotIntegerException(); + } + + public Variable variableValue() throws NotVariableException { + throw new NotVariableException(); + } + + public Variable[] variables() { + return new Variable[0]; + } + + public boolean isPolynomial(Variable variable) { + return false; + } + + public boolean isConstant(Variable variable) { + return false; + } + + public int compareTo(PolynomialWrapper wrapper) { + return content.compareTo(wrapper.content); + } + + public int compareTo(Generic generic) { + if(generic instanceof PolynomialWrapper) { + return compareTo((PolynomialWrapper)generic); + } else { + return compareTo(valueof(generic)); + } + } + + public static Generic factory(Variable variable[]) { + if(variable.length>1) { + Variable var[]=new Variable[variable.length-1]; + for(int i=0;i0?a.multiply(Expression.valueOf(m.literalValue())):a); + } + return s; + } + + public Generic[] elements() { + int size=size(); + Generic a[]=new Generic[size]; + Iterator it=iterator(); + for(int i=0;i0); + } + + static Polynomial factory(Monomial monomialFactory, int modulo, int data_struct, boolean buckets) { + if(buckets) return new GeoBucket(factory(monomialFactory,modulo,data_struct,false)); + else switch(data_struct) { + case Basis.ARRAY: + return new ArrayPolynomial(monomialFactory,generic(modulo)); + case Basis.TREE: + return new TreePolynomial(monomialFactory,generic(modulo)); + case Basis.LIST: + return new ListPolynomial(monomialFactory,generic(modulo)); + default: + switch(modulo) { + case -1: + return new ArrayPolynomialGeneric(monomialFactory,null); + case 0: + return new ArrayPolynomialInteger(monomialFactory); + case 1: + return new ArrayPolynomialRational(monomialFactory); + case 2: + return new ArrayPolynomialBoolean(monomialFactory); + default: + return new ArrayPolynomialModular(monomialFactory,ModularInteger.factory(modulo)); + } + } + } + + static Generic generic(int modulo) { + switch(modulo) { + case -1: + return null; + case 0: + return JSCLInteger.factory; + case 1: + return Rational.factory; + case 2: + return JSCLBoolean.factory; + default: + return ModularInteger.factory(modulo); + } + } + + static Polynomial factory(Polynomial polynomial, int modulo) { + Monomial m=polynomial.monomialFactory; + return factory(m.unknown(),m.ordering(),modulo); + } + + public int compareTo(Polynomial polynomial) { + Iterator it1=iterator(true); + Iterator it2=polynomial.iterator(true); + Term t1=it1.hasNext()?(Term)it1.next():null; + Term t2=it2.hasNext()?(Term)it2.next():null; + while(t1!=null || t2!=null) { + int c=t1==null?1:(t2==null?-1:ordering.compare(t1.monomial(),t2.monomial())); + if(c<0) return -1; + else if(c>0) return 1; + else { + c=t1.coef().compareTo(t2.coef()); + if(c<0) return -1; + else if(c>0) return 1; + t1=it1.hasNext()?(Term)it1.next():null; + t2=it2.hasNext()?(Term)it2.next():null; + } + } + return 0; + } + + public int compareTo(Object o) { + return compareTo((Polynomial)o); + } + + public boolean equals(Object obj) { + if(obj instanceof Polynomial) { + return compareTo((Polynomial)obj)==0; + } else return false; + } + + public String toString() { + StringBuffer buffer=new StringBuffer(); + if(signum()==0) buffer.append("0"); + int i=0; + for(Iterator it=iterator();it.hasNext();i++) { + Term t=(Term)it.next(); + Monomial m=t.monomial(); + Generic a=t.coef(); + if(a instanceof Expression) a=a.signum()>0?GenericVariable.valueOf(a).expressionValue():GenericVariable.valueOf(a.negate()).expressionValue().negate(); + if(a.signum()>0 && i>0) buffer.append("+"); + if(m.degree()==0) buffer.append(a); + else { + if(a.abs().compareTo(JSCLInteger.valueOf(1))==0) { + if(a.signum()<0) buffer.append("-"); + } else buffer.append(a).append("*"); + buffer.append(m); + } + } + return buffer.toString(); + } + + public void toMathML(MathML element, Object data) { + MathML e1=element.element("mrow"); + if(signum()==0) { + MathML e2=element.element("mn"); + e2.appendChild(element.text("0")); + e1.appendChild(e2); + } + int i=0; + for(Iterator it=iterator();it.hasNext();i++) { + Term t=(Term)it.next(); + Monomial m=t.monomial(); + Generic a=t.coef(); + if(a instanceof Expression) a=a.signum()>0?GenericVariable.valueOf(a).expressionValue():GenericVariable.valueOf(a.negate()).expressionValue().negate(); + if(a.signum()>0 && i>0) { + MathML e2=element.element("mo"); + e2.appendChild(element.text("+")); + e1.appendChild(e2); + } + if(m.degree()==0) Expression.separateSign(e1,a); + else { + if(a.abs().compareTo(JSCLInteger.valueOf(1))==0) { + if(a.signum()<0) { + MathML e2=element.element("mo"); + e2.appendChild(element.text("-")); + e1.appendChild(e2); + } + } else Expression.separateSign(e1,a); + m.toMathML(e1,null); + } + } + element.appendChild(e1); + } +} diff --git a/src/misc/src/jscl/math/polynomial/SmallMonomial.java b/src/misc/src/jscl/math/polynomial/SmallMonomial.java new file mode 100644 index 00000000..00f1f329 --- /dev/null +++ b/src/misc/src/jscl/math/polynomial/SmallMonomial.java @@ -0,0 +1,174 @@ +package jscl.math.polynomial; + +import jscl.math.NotDivisibleException; +import jscl.math.Variable; + +class SmallMonomial extends Monomial { + static final Ordering lexicographic=SmallLexicographic.ordering; + static final Ordering totalDegreeLexicographic=SmallTotalDegreeLexicographic.ordering; + static final Ordering degreeReverseLexicographic=SmallDegreeReverseLexicographic.ordering; + static final int log2n=3; + static final int log2p=5-log2n; + static final int nmask=(1<<(1<>log2p)+1,unknown,ordering); + } + + SmallMonomial(int length, Variable unknown[], Ordering ordering) { + super(length,unknown,ordering); + } + + public Monomial multiply(Monomial monomial) { + Monomial m=newinstance(); + for(int i=0;i>log2p; + int r=(i&pmask)<>r)&nmask; + int b=(monomial.element[q]>>r)&nmask; + int c=a+b; + if(c>nmask) throw new ArithmeticException(); + m.element[q]|=c<>log2p; + int r=(i&pmask)<>r)&nmask; + int b=(monomial.element[q]>>r)&nmask; + if(a>log2p; + int r=(i&pmask)<>r)&nmask; + int b=(monomial.element[q]>>r)&nmask; + int c=a-b; + if(c<0) throw new NotDivisibleException(); + m.element[q]|=c<>log2p; + int r=(i&pmask)<>r)&nmask; + int b=(monomial.element[q]>>r)&nmask; + int c=Math.min(a,b); + m.element[q]|=c<>log2p; + int r=(i&pmask)<>r)&nmask; + int b=(monomial.element[q]>>r)&nmask; + int c=Math.max(a,b); + m.element[q]|=c<>log2p; + int r=(n&pmask)<>r)&nmask; + } + + void put(int n, int integer) { + if(reverse()) n=unknown.length-1-n; + int q=n>>log2p; + int r=(n&pmask)<>r)&nmask; + int c=a+integer; + if(c>nmask) throw new ArithmeticException(); + element[q]|=c<=0;i--) { + long l1=c1[i]&0xffffffffl; + long l2=c2[i]&0xffffffffl; + if(l1l2) return 1; + } + return 0; + } +} + +class SmallTotalDegreeLexicographic extends SmallLexicographic implements DegreeOrdering { + public static final Ordering ordering=new SmallTotalDegreeLexicographic(); + + SmallTotalDegreeLexicographic() {} + + + public int compare(Monomial m1, Monomial m2) { + if(m1.degreem2.degree) return 1; + else return super.compare(m1,m2); + } +} + +class SmallDegreeReverseLexicographic extends Ordering implements DegreeOrdering { + public static final Ordering ordering=new SmallDegreeReverseLexicographic(); + + SmallDegreeReverseLexicographic() {} + + public int compare(Monomial m1, Monomial m2) { + if(m1.degreem2.degree) return 1; + else { + int c1[]=m1.element; + int c2[]=m2.element; + int n=c1.length; + for(int i=n-1;i>=0;i--) { + long l1=c1[i]&0xffffffffl; + long l2=c2[i]&0xffffffffl; + if(l1>l2) return -1; + else if(l10:iterator.hasNext(); + } + + public Object next() { + if(direction) { + Monomial m=(Monomial)map.lastKey(); + map=content.headMap(m); + return term(m); + } else { + return term((Map.Entry)iterator.next()); + } + } + + public void remove() { + throw new UnsupportedOperationException(); + } + } + + Term term(Map.Entry entry) { + return new Term((Monomial)entry.getKey(),(Generic)entry.getValue()); + } + + Term term(Monomial monomial) { + return new Term(monomial,null) { + public Generic coef() { + return coef==null?coefficient(monomial):coef; + } + }; + } + + SortedMap subContent(Monomial monomial, boolean direction) { + if(monomial==null) return content; + return direction?content.headMap(monomial):content.tailMap(monomial); + } + + public Polynomial subtract(Polynomial polynomial) { + if(polynomial.signum()==0) return this; + if(mutable) { + TreePolynomial q=(TreePolynomial)polynomial; + Iterator it=q.content.entrySet().iterator(); + while(it.hasNext()) { + Map.Entry e=(Map.Entry)it.next(); + Monomial m=(Monomial)e.getKey(); + Generic a=(Generic)e.getValue(); + Generic s=coefficient(m).subtract(a); + if(s.signum()==0) content.remove(m); + else content.put(m,s); + } + degree=degree(this); + sugar=Math.max(sugar,q.sugar); + normalized=false; + return this; + } else return copy().subtract(polynomial); + } + + public Polynomial multiplyAndSubtract(Generic generic, Polynomial polynomial) { + if(generic.signum()==0) return this; + if(generic.compareTo(JSCLInteger.valueOf(1))==0) return subtract(polynomial); + if(mutable) { + TreePolynomial q=(TreePolynomial)polynomial; + Iterator it=q.content.entrySet().iterator(); + while(it.hasNext()) { + Map.Entry e=(Map.Entry)it.next(); + Monomial m=(Monomial)e.getKey(); + Generic a=((Generic)e.getValue()).multiply(generic); + Generic s=coefficient(m).subtract(a); + if(s.signum()==0) content.remove(m); + else content.put(m,s); + } + degree=degree(this); + sugar=Math.max(sugar,q.sugar); + normalized=false; + return this; + } else return copy().multiplyAndSubtract(generic,polynomial); + } + + public Polynomial multiplyAndSubtract(Monomial monomial, Generic generic, Polynomial polynomial) { + if(generic.signum()==0) return this; + if(monomial.degree()==0) return multiplyAndSubtract(generic,polynomial); + if(mutable) { + TreePolynomial q=(TreePolynomial)polynomial; + Iterator it=q.content.entrySet().iterator(); + while(it.hasNext()) { + Map.Entry e=(Map.Entry)it.next(); + Monomial m=((Monomial)e.getKey()).multiply(monomial); + Generic a=((Generic)e.getValue()).multiply(generic); + Generic s=coefficient(m).subtract(a); + if(s.signum()==0) content.remove(m); + else content.put(m,s); + } + degree=degree(this); + sugar=Math.max(sugar,q.sugar+monomial.degree()); + normalized=false; + return this; + } else return copy().multiplyAndSubtract(monomial,generic,polynomial); + } + + public Polynomial multiply(Generic generic) { + if(generic.signum()==0) return valueof(JSCLInteger.valueOf(0)); + if(generic.compareTo(JSCLInteger.valueOf(1))==0) return this; + if(mutable) { + Iterator it=content.entrySet().iterator(); + while(it.hasNext()) { + Map.Entry e=(Map.Entry)it.next(); + e.setValue(((Generic)e.getValue()).multiply(generic)); + } + normalized=false; + return this; + } else return copy().multiply(generic); + } + + public Polynomial multiply(Monomial monomial) { + if(defined) { + TreePolynomial p=newinstance(); + Iterator it=content.entrySet().iterator(); + while(it.hasNext()) { + Map.Entry e=(Map.Entry)it.next(); + Monomial m=((Monomial)e.getKey()).multiply(monomial); + Generic a=(Generic)e.getValue(); + Generic s=p.coefficient(m).add(a); + if(s.signum()==0) p.content.remove(m); + else p.content.put(m,s); + } + p.degree=degree(p); + p.sugar=sugar+monomial.degree(); + return p; + } else { + if(monomial.degree()==0) return this; + TreePolynomial p=newinstance(); + Iterator it=content.entrySet().iterator(); + while(it.hasNext()) { + Map.Entry e=(Map.Entry)it.next(); + p.content.put(((Monomial)e.getKey()).multiply(monomial),(Generic)e.getValue()); + } + 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; + if(mutable) { + Iterator it=content.entrySet().iterator(); + while(it.hasNext()) { + Map.Entry e=(Map.Entry)it.next(); + e.setValue(((Generic)e.getValue()).divide(generic)); + } + normalized=false; + return this; + } else return copy().divide(generic); + } + + public Polynomial divide(Monomial monomial) throws ArithmeticException { + if(monomial.degree()==0) return this; + TreePolynomial p=newinstance(); + Iterator it=content.entrySet().iterator(); + while(it.hasNext()) { + Map.Entry e=(Map.Entry)it.next(); + p.content.put(((Monomial)e.getKey()).divide(monomial),(Generic)e.getValue()); + } + p.degree=degree+monomial.degree(); + p.sugar=sugar+monomial.degree(); + return p; + } + + public Polynomial gcd(Polynomial polynomial) { + throw new UnsupportedOperationException(); + } + + public int degree() { + return degree; + } + + public Polynomial valueof(Polynomial polynomial) { + TreePolynomial p=newinstance(); + p.init(polynomial); + return p; + } + + public Polynomial valueof(Generic generic) { + TreePolynomial p=newinstance(); + p.init(generic); + return p; + } + + public Polynomial valueof(Monomial monomial) { + TreePolynomial p=newinstance(); + p.init(monomial); + return p; + } + + public Polynomial freeze() { + mutable=false; + return this; + } + + public Term head() { + return content.size()>0?term((Monomial)content.lastKey()):null; + } + + public Term tail() { + return content.size()>0?term((Monomial)content.firstKey()):null; + } + + public Generic coefficient(Monomial monomial) { + Generic a=(Generic)content.get(monomial); + return a==null?coefficient(JSCLInteger.valueOf(0)):a; + } + + void init(Polynomial polynomial) { + TreePolynomial q=(TreePolynomial)polynomial; + content.putAll(q.content); + degree=q.degree; + sugar=q.sugar; + } + + void init(Expression expression) { + int sugar=0; + int n=expression.size(); + for(int i=0;i0?en.multiply(Expression.valueOf(l)):en); + Generic a1=coefficient(m); + Generic a=a1.add(a2); + if(a.signum()==0) content.remove(m); + else content.put(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) content.put(monomial(Literal.valueOf()),a); + degree=0; + sugar=0; + } + } + + void init(Monomial monomial) { + content.put(monomial,coefficient(JSCLInteger.valueOf(1))); + degree=monomial.degree(); + sugar=monomial.degree(); + } + + protected TreePolynomial newinstance() { + return new TreePolynomial(monomialFactory,coefFactory); + } +} diff --git a/src/misc/src/jscl/math/polynomial/UnivariatePolynomial.java b/src/misc/src/jscl/math/polynomial/UnivariatePolynomial.java new file mode 100644 index 00000000..ad500b85 --- /dev/null +++ b/src/misc/src/jscl/math/polynomial/UnivariatePolynomial.java @@ -0,0 +1,493 @@ +package jscl.math.polynomial; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import jscl.math.Expression; +import jscl.math.Generic; +import jscl.math.JSCLInteger; +import jscl.math.Literal; +import jscl.math.NotDivisibleException; +import jscl.math.Variable; +import jscl.math.function.Inv; +import jscl.util.ArrayUtils; + +public class UnivariatePolynomial extends Polynomial { + protected final Variable variable; + Generic content[]=new Generic[8]; + int degree; + + protected UnivariatePolynomial(Variable variable) { + this(variable,null); + } + + UnivariatePolynomial(Variable variable, Generic coefFactory) { + super(Monomial.factory(new Variable[] {variable}),coefFactory); + this.variable=variable; + } + + public Variable variable() { + return variable; + } + + public int size() { + return degree+1; + } + + 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; + if(direction) { + index=indexOf(current,true); + } else { + index=indexOf(current,false); + if(current!=null && get(index).signum()!=0) index++; + } + seek(); + } + + void seek() { + if(direction) while(index>0 && get(index).signum()==0) index--; + else while(index<=degree && get(index).signum()==0) index++; + } + + public boolean hasNext() { + return direction?index>0:index<=degree; + } + + public Object next() { + Term t=direction?term(--index):term(index++); + seek(); + return t; + } + + public void remove() { + throw new UnsupportedOperationException(); + } + } + + Term term(int n) { + return new Term(monomial(Literal.valueOf(variable,n)),get(n)); + } + + int indexOf(Monomial monomial, boolean direction) { + if(monomial==null) return direction?degree+1:0; + return monomial.degree(); + } + + public Polynomial add(Polynomial polynomial) { + UnivariatePolynomial p=newinstance(); + UnivariatePolynomial q=(UnivariatePolynomial)polynomial; + int d=Math.max(degree,q.degree); + for(int i=d;i>=0;i--) { + p.put(i,get(i).add(q.get(i))); + } + return p; + } + + public Polynomial subtract(Polynomial polynomial) { + UnivariatePolynomial p=newinstance(); + UnivariatePolynomial q=(UnivariatePolynomial)polynomial; + int d=Math.max(degree,q.degree); + for(int i=d;i>=0;i--) { + p.put(i,get(i).subtract(q.get(i))); + } + return p; + } + + public Polynomial multiply(Polynomial polynomial) { + UnivariatePolynomial p=newinstance(); + UnivariatePolynomial q=(UnivariatePolynomial)polynomial; + for(int i=degree;i>=0;i--) { + for(int j=q.degree;j>=0;j--) { + p.put(i+j,get(i).multiply(q.get(j))); + } + } + return p; + } + + public Polynomial multiply(Generic generic) { + UnivariatePolynomial p=newinstance(); + for(int i=degree;i>=0;i--) { + p.put(i,get(i).multiply(generic)); + } + return p; + } + + public Polynomial multiply(Monomial monomial, Generic generic) { + UnivariatePolynomial p=newinstance(); + int d=monomial.degree(); + for(int i=degree;i>=0;i--) { + p.put(i+d,get(i).multiply(generic)); + } + for(int i=d-1;i>=0;i--) { + p.put(i,JSCLInteger.valueOf(0)); + } + return p; + } + + public Polynomial multiply(Monomial monomial) { + return multiply(monomial,JSCLInteger.valueOf(1)); + } + + public Polynomial divide(Generic generic) throws ArithmeticException { + UnivariatePolynomial p=newinstance(); + for(int i=degree;i>=0;i--) { + p.put(i,get(i).divide(generic)); + } + return p; + } + + public Polynomial divide(Monomial monomial) throws ArithmeticException { + UnivariatePolynomial p=newinstance(); + int d=monomial.degree(); + for(int i=d-1;i>=0;i--) { + if(get(i).signum()==0); + else throw new NotDivisibleException(); + } + for(int i=degree;i>=d;i--) { + p.put(i-d,get(i)); + } + return p; + } + + public Polynomial[] divideAndRemainder(Polynomial polynomial) throws ArithmeticException { + UnivariatePolynomial p[]={newinstance(),this}; + UnivariatePolynomial q=(UnivariatePolynomial)polynomial; + if(p[1].signum()==0) return p; + for(int i=p[1].degree-q.degree;i>=0;i--) { + p[0].put(i,p[1].get(i+q.degree).divide(q.get(q.degree))); + UnivariatePolynomial r=newinstance(); + for(int j=i+q.degree-1;j>=0;j--) { + Generic a=p[1].get(j); + r.put(j,a.subtract(q.get(j-i).multiply(p[0].get(i)))); + } + p[1]=r; + } + return p; + } + + public Polynomial remainderUpToCoefficient(Polynomial polynomial) throws ArithmeticException { + UnivariatePolynomial p=this; + UnivariatePolynomial q=(UnivariatePolynomial)polynomial; + if(p.signum()==0) return p; + for(int i=p.degree-q.degree;i>=0;i--) { + UnivariatePolynomial r=newinstance(); + for(int j=i+q.degree-1;j>=0;j--) { + Generic a=p.get(j).multiply(q.get(q.degree)); + r.put(j,a.subtract(q.get(j-i).multiply(p.get(i+q.degree)))); + } + p=r; + } + return p; + } + + public Polynomial gcd(Polynomial polynomial) { + UnivariatePolynomial p=this; + UnivariatePolynomial q=(UnivariatePolynomial)polynomial; + if(p.signum()==0) return q; + else if(q.signum()==0) return p; + if(p.degree0) { + UnivariatePolynomial r=(UnivariatePolynomial)p.remainderUpToCoefficient(q).divide(beta); + if(d>1) phi=q.get(q.degree).negate().pow(d).divide(phi.pow(d-1)); + else phi=q.get(q.degree).negate().pow(d).multiply(phi.pow(1-d)); + p=q; + q=r; + d=p.degree-q.degree; + beta=p.get(p.degree).negate().multiply(phi.pow(d)); + } + if(q.signum()==0) { + p=(UnivariatePolynomial)p.normalize(); + } else { + p=newinstance(); + p.put(0,JSCLInteger.valueOf(1)); + } + return p.multiply(gcd1.gcd(gcd2)); + } + + public Generic gcd() { + Generic a=coefficient(JSCLInteger.valueOf(0)); + for(int i=degree;i>=0;i--) a=a.gcd(get(i)); + return a.signum()==signum()?a:a.negate(); + } + + public Monomial monomialGcd() { + return monomial(tail()); + } + + public int degree() { + return degree; + } + + public UnivariatePolynomial valueof(Generic generic[]) { + UnivariatePolynomial p=newinstance(); + p.init(generic); + return p; + } + + public Polynomial valueof(Polynomial polynomial) { + throw new UnsupportedOperationException(); + } + + public Polynomial valueof(Generic generic) { + UnivariatePolynomial p=newinstance(); + p.init(generic); + return p; + } + + public Polynomial valueof(Monomial monomial) { + throw new UnsupportedOperationException(); + } + + public Polynomial freeze() { + return this; + } + + public Term head() { + return term(degree); + } + + public Generic coefficient(Monomial monomial) { + return term(monomial.degree()).coef(); + } + + public Polynomial reduce(Generic generic, Monomial monomial, Polynomial polynomial, boolean inPlace) { + throw new UnsupportedOperationException(); + } + + public Generic genericValue() { + Generic s=JSCLInteger.valueOf(0); + for(int i=degree;i>=0;i--) { + Generic a=get(i).expressionValue(); + s=s.add(i>0?a.multiply(Expression.valueOf(Literal.valueOf(variable,i))):a); + } + return s; + } + + public Generic[] elements() { + Generic a[]=new Generic[degree+1]; + for(int i=degree;i>=0;i--) a[i]=get(i); + return a; + } + + public UnivariatePolynomial derivative(Variable variable) { + return (UnivariatePolynomial)derivative().multiply(this.variable.derivative(variable)); + } + + public Generic substitute(Generic generic) { + Generic s=JSCLInteger.valueOf(0); + for(int i=degree;i>=0;i--) { + s=s.add(get(i).multiply(generic.pow(i))); + } + return s; + } + + public Generic solve() { + if(degree==1) { + return get(0).multiply(new Inv(get(1)).evaluate()).negate(); + } else return null; + } + + public Generic[] identification(UnivariatePolynomial polynomial) { + UnivariatePolynomial p=this; + UnivariatePolynomial q=polynomial; + if(p.degree=0;i--) a[r.degree-i]=r.get(i); + return a; + } + + public Generic resultant(UnivariatePolynomial polynomial) { + UnivariatePolynomial p=this; + UnivariatePolynomial q=polynomial; + if(p.degree0) { + UnivariatePolynomial r=(UnivariatePolynomial)p.remainderUpToCoefficient(q).divide(beta); + if(d>1) phi=q.get(q.degree).negate().pow(d).divide(phi.pow(d-1)); + else phi=q.get(q.degree).negate().pow(d).multiply(phi.pow(1-d)); + p=q; + q=r; + d=p.degree-q.degree; + beta=p.get(p.degree).negate().multiply(phi.pow(d)); + } + return q.get(0); + } + + public UnivariatePolynomial[] remainderSequence(UnivariatePolynomial polynomial) { + UnivariatePolynomial p=this; + UnivariatePolynomial q=polynomial; + if(p.degree0) { + UnivariatePolynomial r=(UnivariatePolynomial)p.remainderUpToCoefficient(q).divide(beta); + if(d>1) phi=q.get(q.degree).negate().pow(d).divide(phi.pow(d-1)); + else phi=q.get(q.degree).negate().pow(d).multiply(phi.pow(1-d)); + p=q; + q=r; + s[q.degree]=q; + d=p.degree-q.degree; + beta=p.get(p.degree).negate().multiply(phi.pow(d)); + } + return s; + } + + public UnivariatePolynomial squarefree() { + return (UnivariatePolynomial)divide(gcd(derivative())); + } + + public UnivariatePolynomial[] squarefreeDecomposition() { + return SquarefreeDecomposition.compute(this); + } + + public UnivariatePolynomial antiderivative() { + UnivariatePolynomial p=newinstance(); + for(int i=degree;i>=0;i--) { + p.put(i+1,get(i).multiply(new Inv(JSCLInteger.valueOf(i+1)).evaluate())); + } + return p; + } + + public UnivariatePolynomial derivative() { + UnivariatePolynomial p=newinstance(); + for(int i=degree-1;i>=0;i--) { + p.put(i,get(i+1).multiply(JSCLInteger.valueOf(i+1))); + } + return p; + } + + public int compareTo(Polynomial polynomial) { + UnivariatePolynomial p=(UnivariatePolynomial)polynomial; + int d=Math.max(degree,p.degree); + for(int i=d;i>=0;i--) { + Generic a1=get(i); + Generic a2=p.get(i); + int c=a1.compareTo(a2); + if(c<0) return -1; + else if(c>0) return 1; + } + return 0; + } + + void init(Generic generic[]) { + for(int i=0;i0) put(m.degree(),coefficient(en.multiply(Expression.valueOf(l)))); + else put(m.degree(),coefficient(en)); + } + } + + protected void init(Generic generic) { + if(generic instanceof Expression) { + init((Expression)generic); + } else put(0,coefficient(generic)); + } + + void put(int n, Generic generic) { + Generic a=generic.add(get(n)); + if(a.signum()==0) { + if(n<=degree) content[n]=null; + if(n==degree) { + while(n>0 && content[n]==null) n--; + degree=n; + } + } else { + if(n>=content.length) resize(n); + content[n]=a; + degree=Math.max(degree,n); + } + } + + void resize(int n) { + int length=content.length<<1; + while(n>=length) length<<=1; + Generic content[]=new Generic[length]; + System.arraycopy(this.content,0,content,0,this.content.length); + this.content=content; + } + + public Generic get(int n) { + Generic a=n<0 || n>degree?null:content[n]; + return a==null?JSCLInteger.valueOf(0):a; + } + + protected UnivariatePolynomial newinstance() { + return new UnivariatePolynomial(variable,coefFactory); + } +} + +class SquarefreeDecomposition { + final List list=new ArrayList(); + + static UnivariatePolynomial[] compute(UnivariatePolynomial polynomial) { + SquarefreeDecomposition sd=new SquarefreeDecomposition(); + Polynomial p[]=polynomial.gcdAndNormalize(); + sd.init((UnivariatePolynomial)p[0]); + sd.process((UnivariatePolynomial)p[1]); + return sd.getValue(); + } + + void init(UnivariatePolynomial polynomial) { + list.add(polynomial); + } + + void process(UnivariatePolynomial polynomial) { + UnivariatePolynomial r=(UnivariatePolynomial)polynomial.gcd(polynomial.derivative()); + UnivariatePolynomial s=(UnivariatePolynomial)polynomial.divide(r); + list.add(s.divide(s.gcd(r))); + if(r.degree()==0); + else process(r); + } + + UnivariatePolynomial[] getValue() { + return (UnivariatePolynomial[])ArrayUtils.toArray(list,new UnivariatePolynomial[list.size()]); + } +} diff --git a/src/misc/src/jscl/math/polynomial/groebner/Block.java b/src/misc/src/jscl/math/polynomial/groebner/Block.java new file mode 100644 index 00000000..5be3b126 --- /dev/null +++ b/src/misc/src/jscl/math/polynomial/groebner/Block.java @@ -0,0 +1,60 @@ +package jscl.math.polynomial.groebner; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import jscl.math.Debug; +import jscl.math.polynomial.Basis; +import jscl.math.polynomial.DegreeOrdering; +import jscl.math.polynomial.Ordering; +import jscl.math.polynomial.Polynomial; + +class Block extends Standard { + boolean degree; + + Block(Ordering ordering, int flags) { + super(flags); + degree=ordering instanceof DegreeOrdering; + } + + void compute() { + Debug.println("compute"); + int degree=0; + while(!pairs.isEmpty()) { + List list=new ArrayList(); + Iterator it=pairs.keySet().iterator(); + while(it.hasNext()) { + Pair pa=(Pair)it.next(); + int d=(flags&Basis.SUGAR)>0?pa.sugar:pa.scm.degree(); + if(degree==0) degree=d; + else if(d>degree || !this.degree) break; + list.add(pa); + } + process(list); + remove(list); + degree=0; + } + } + + void add(List list) { + super.add(ReducedRowEchelonForm.compute(list)); + } + + void process(List pairs) { + List list=new ArrayList(); + Iterator it=pairs.iterator(); + while(it.hasNext()) { + Pair pa=(Pair)it.next(); + if(criterion(pa)) continue; + Polynomial p=reduce(pa,polys); + if(p.signum()!=0) list.add(p); + npairs++; + } + add(list); + } + + void remove(List pairs) { + Iterator it=pairs.iterator(); + while(it.hasNext()) remove((Pair)it.next()); + } +} diff --git a/src/misc/src/jscl/math/polynomial/groebner/F4.java b/src/misc/src/jscl/math/polynomial/groebner/F4.java new file mode 100644 index 00000000..b79d3a22 --- /dev/null +++ b/src/misc/src/jscl/math/polynomial/groebner/F4.java @@ -0,0 +1,35 @@ +package jscl.math.polynomial.groebner; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import jscl.math.polynomial.Ordering; +import jscl.math.polynomial.Polynomial; + +class F4 extends Block { + List reduction=new ArrayList(); + + F4(Ordering ordering, int flags) { + super(ordering,flags); + } + + void add(List list) { + Iterator it=list.iterator(); + while(it.hasNext()) { + Polynomial p=(Polynomial)it.next(); + if(p.signum()!=0) add(p); + } + } + + void process(List pairs) { + List list=new ArrayList(); + Iterator it=pairs.iterator(); + while(it.hasNext()) { + Pair pa=(Pair)it.next(); + if(criterion(pa)) continue; + list.add(pa); + } + add(F4Reduction.compute(list,polys,reduction,flags)); + npairs+=list.size(); + } +} diff --git a/src/misc/src/jscl/math/polynomial/groebner/F4Reduction.java b/src/misc/src/jscl/math/polynomial/groebner/F4Reduction.java new file mode 100644 index 00000000..6b6273b6 --- /dev/null +++ b/src/misc/src/jscl/math/polynomial/groebner/F4Reduction.java @@ -0,0 +1,98 @@ +package jscl.math.polynomial.groebner; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; +import jscl.math.Debug; +import jscl.math.polynomial.Basis; +import jscl.math.polynomial.Monomial; +import jscl.math.polynomial.Polynomial; +import jscl.math.polynomial.Term; + +class F4Reduction { + final Collection ideal; + final List list; + final int flags; + final List polys=new ArrayList(); + final List content=new ArrayList(); + final Map considered=new TreeMap(); + final Map head=new TreeMap(); + final Map proj=new TreeMap(); + + F4Reduction(Collection ideal, List list, int flags) { + this.ideal=ideal; + this.list=list; + this.flags=flags; + } + + static List compute(List pairs, Collection ideal, List list, int flags) { + F4Reduction r=new F4Reduction(ideal,list,flags); + r.compute(pairs); + return r.content; + } + + void compute(List pairs) { + Iterator it=pairs.iterator(); + while(it.hasNext()) { + Pair pa=(Pair)it.next(); + considered.put(pa.scm,null); + add(pa); + } + process(); + if((flags&Basis.F4_SIMPLIFY)>0) list.add(this); + } + + void add(Pair pair) { + Debug.println(pair); + Projection pr[]=new Projection[] {new Projection(pair,0),new Projection(pair,1)}; + for(int i=0;i0) return 1; + else { + c=polynomial[1].index()-pair.polynomial[1].index(); + if(c<0) return -1; + else if(c>0) return 1; + else { + c=polynomial[0].index()-pair.polynomial[0].index(); + if(c<0) return -1; + else if(c>0) return 1; + else return 0; + } + } + } + + public int compareTo(Object o) { + return compareTo((Pair)o); + } + + public String toString() { + return "{"+polynomial[0].index()+", "+polynomial[1].index()+"}, "+sugar+", "+reduction; + } +} diff --git a/src/misc/src/jscl/math/polynomial/groebner/Projection.java b/src/misc/src/jscl/math/polynomial/groebner/Projection.java new file mode 100644 index 00000000..6aa75c12 --- /dev/null +++ b/src/misc/src/jscl/math/polynomial/groebner/Projection.java @@ -0,0 +1,73 @@ +package jscl.math.polynomial.groebner; + +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import jscl.math.polynomial.Monomial; +import jscl.math.polynomial.Polynomial; + +class Projection implements Comparable { + final Monomial monomial; + final Polynomial polynomial; + + Projection(Pair pair, int index) { + this(pair.scm.divide(pair.monomial[index]),pair.polynomial[index]); + } + + Projection(Monomial monomial, Polynomial polynomial) { + this.monomial=monomial; + this.polynomial=polynomial; + } + + Monomial scm() { + return polynomial.head().monomial().multiply(monomial); + } + + Polynomial mult() { + return polynomial.multiply(monomial); + } + + Projection simplify(List list) { + Monomial t=monomial; + if(t.degree()>0) { + Monomial m=polynomial.head().monomial(); + int n=list.size(); + for(int i=0;i0) return 1; + else { + c=polynomial.index()-proj.polynomial.index(); + if(c<0) return -1; + else if(c>0) return 1; + else return 0; + } + } + + public int compareTo(Object o) { + return compareTo((Projection)o); + } + + public String toString() { + return "{"+monomial+", "+polynomial.head().monomial()+"}"; + } +} diff --git a/src/misc/src/jscl/math/polynomial/groebner/ReducedRowEchelonForm.java b/src/misc/src/jscl/math/polynomial/groebner/ReducedRowEchelonForm.java new file mode 100644 index 00000000..2e0a2258 --- /dev/null +++ b/src/misc/src/jscl/math/polynomial/groebner/ReducedRowEchelonForm.java @@ -0,0 +1,57 @@ +package jscl.math.polynomial.groebner; + +import java.util.ArrayList; +import java.util.List; +import jscl.math.Generic; +import jscl.math.polynomial.Monomial; +import jscl.math.polynomial.Polynomial; + +class ReducedRowEchelonForm { + List content=new ArrayList(); + + ReducedRowEchelonForm(List list) { + content.addAll(list); + } + + static List compute(List list) { + ReducedRowEchelonForm f=new ReducedRowEchelonForm(list); + f.compute(); + return f.content; + } + + void compute() { + int n=content.size(); + for(int i=0;i=0;i--) reduce(i,true); + } + + void reduce(int pivot, boolean direction) { + Polynomial p=polynomial(pivot); + content.set(pivot,p=p.normalize().freeze()); + if(p.signum()==0) return; + Monomial m=p.head().monomial(); + int b=direction?0:pivot+1; + int n=direction?pivot:content.size(); + for(int i=b;i0?", ":"").append(p); + } + buffer.append("}"); + return buffer.toString(); + } +} diff --git a/src/misc/src/jscl/math/polynomial/groebner/Standard.java b/src/misc/src/jscl/math/polynomial/groebner/Standard.java new file mode 100644 index 00000000..fe5c9e26 --- /dev/null +++ b/src/misc/src/jscl/math/polynomial/groebner/Standard.java @@ -0,0 +1,227 @@ +package jscl.math.polynomial.groebner; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; +import jscl.math.Debug; +import jscl.math.Generic; +import jscl.math.polynomial.Basis; +import jscl.math.polynomial.Monomial; +import jscl.math.polynomial.Ordering; +import jscl.math.polynomial.Polynomial; +import jscl.util.ArrayUtils; + +public class Standard { + final int flags; + final Comparator comparator; + final Map pairs; + final List polys=new ArrayList(); + final Map removed=new TreeMap(); + int npairs; + int npolys; + + Standard(int flags) { + this.flags=flags; + pairs=new TreeMap(comparator=(flags&Basis.SUGAR)>0?Sugar.comparator:Natural.comparator); + } + + public static Basis compute(Basis basis) { + return compute(basis,0); + } + + public static Basis compute(Basis basis, int flags) { + return compute(basis,flags,(flags&Basis.INSTRUMENTED)>0); + } + + static Basis compute(Basis basis, int flags, boolean instrumented) { + Standard a=instrumented?new Instrumented(flags):algorithm(basis.ordering(),flags); + a.computeValue(basis); + basis=basis.valueof(a.elements()); + if(instrumented) return compute(basis,flags,false); + return basis; + } + + static Standard algorithm(Ordering ordering, int flags) { + switch(flags&Basis.ALGORITHM) { + case Basis.F4: + return new F4(ordering,flags); + case Basis.BLOCK: + return new Block(ordering,flags); + default: + return new Standard(flags); + } + } + + void computeValue(Basis basis) { + Debug.println(basis); + populate(basis); + npolys=0; + compute(); + remove(); + reduce(); + Debug.println("signature = ("+npairs+", "+npolys+", "+polys.size()+")"); + } + + void populate(Basis basis) { + List list=new ArrayList(); + Generic a[]=basis.elements(); + for(int i=0;i0) makePairsGM(polynomial); + else makePairs(polynomial); + polys.add(polynomial); + npolys++; + } + + boolean criterion(Pair pair) { + return (flags&Basis.GM_SETTING)>0?false:b_criterion(pair); + } + + void makePairs(Polynomial polynomial) { + Iterator it=polys.iterator(); + while(it.hasNext()) { + Polynomial p=(Polynomial)it.next(); + Pair pa=new Pair(p,polynomial); + if(!pa.coprime) pairs.put(pa,null); + } + } + + boolean b_criterion(Pair pair) { + Iterator it=polys.iterator(); + while(it.hasNext()) { + Polynomial p=(Polynomial)it.next(); + if(pair.scm.multiple(p.head().monomial())) { + Pair pa1=new Pair(sort(pair.polynomial[0],p)); + Pair pa2=new Pair(sort(pair.polynomial[1],p)); + if(considered(pa1) && considered(pa2)) return true; + } + } + return false; + } + + boolean considered(Pair pair) { + return !pairs.containsKey(pair); + } + + Polynomial[] sort(Polynomial p1, Polynomial p2) { + return p1.index()0 && (flags&Basis.FUSSY)>0?Sugar.comparator:Natural.comparator); + it=polys.iterator(); + while(it.hasNext()) { + Polynomial p=(Polynomial)it.next(); + Pair pa=new Pair(p,polynomial); + pairs.put(pa,null); + map.put(pa,null); + } + list=ArrayUtils.list(map.keySet()); + n=list.size(); + for(int i=0;i0 && (flags&Basis.FUSSY)>0?Sugar.comparator.compare(p1,p2)>0:true); + } + + void remove() { + Iterator it=polys.iterator(); + while(it.hasNext()) if(removed.containsKey(it.next())) it.remove(); + } + + void reduce() { + Debug.println("reduce"); + Map map=new TreeMap(); + int size=polys.size(); + for(int i=0;ipa2.sugar) return 1; + else return pa1.compareTo(pa2); + } + + public int compare(Object o1, Object o2) { + return compare((Pair)o1,(Pair)o2); + } +} diff --git a/src/misc/src/jscl/mathml/MathML.java b/src/misc/src/jscl/mathml/MathML.java new file mode 100644 index 00000000..74e655f2 --- /dev/null +++ b/src/misc/src/jscl/mathml/MathML.java @@ -0,0 +1,66 @@ +package jscl.mathml; + +import java.io.ByteArrayOutputStream; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; +import org.apache.xerces.dom.CoreDocumentImpl; +import org.apache.xerces.dom.DocumentTypeImpl; +import org.apache.xerces.dom.ElementImpl; +import org.apache.xerces.dom.TextImpl; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +public class MathML { + static Transformer xhtml; + Node node; + + MathML(Node node) { + this.node=node; + } + + public Document document() { + return node instanceof CoreDocumentImpl?(Document)node:node.getOwnerDocument(); + } + + public MathML(String qualifiedName, String publicID, String systemID) { + this(new CoreDocumentImpl()); + CoreDocumentImpl document=(CoreDocumentImpl)document(); + document.setXmlEncoding("utf-8"); + document.appendChild(new DocumentTypeImpl(document,qualifiedName,publicID,systemID)); + } + + public MathML element(String name) { + CoreDocumentImpl document=(CoreDocumentImpl)document(); + return new MathML(new ElementImpl(document,name)); + } + + public void setAttribute(String name, String value) { + ((Element)node).setAttribute(name, value); + } + + public MathML text(String data) { + CoreDocumentImpl document=(CoreDocumentImpl)document(); + return new MathML(new TextImpl(document,data)); + } + + public void appendChild(MathML math) { + node.appendChild(math.node); + } + + public String toString() { + ByteArrayOutputStream os=new ByteArrayOutputStream(); + try { + transformer().transform(new DOMSource(node), new StreamResult(os)); + } catch (TransformerException e) {} + String s=os.toString(); + return s.substring(s.indexOf(">")+1); + } + + static Transformer transformer() throws TransformerException { + return xhtml==null?xhtml=TransformerFactory.newInstance().newTransformer():xhtml; + } +} diff --git a/src/misc/src/jscl/text/BracketedExpression.java b/src/misc/src/jscl/text/BracketedExpression.java new file mode 100644 index 00000000..35b4821e --- /dev/null +++ b/src/misc/src/jscl/text/BracketedExpression.java @@ -0,0 +1,36 @@ +package jscl.text; + +import jscl.math.ExpressionVariable; +import jscl.math.Generic; + +public class BracketedExpression extends Parser { + public static final Parser parser=new BracketedExpression(); + + private BracketedExpression() {} + + public Object parse(String str, int pos[]) throws ParseException { + int pos0=pos[0]; + Generic a; + skipWhitespaces(str,pos); + if(pos[0]='A' && c<='Z') || (c>='a' && c<='z') || c=='_'; + } +} diff --git a/src/misc/src/jscl/text/ImplicitFunctionParser.java b/src/misc/src/jscl/text/ImplicitFunctionParser.java new file mode 100644 index 00000000..efdad98d --- /dev/null +++ b/src/misc/src/jscl/text/ImplicitFunctionParser.java @@ -0,0 +1,137 @@ +package jscl.text; + +import java.util.ArrayList; +import java.util.List; +import jscl.math.Generic; +import jscl.math.function.ImplicitFunction; +import jscl.util.ArrayUtils; + +public class ImplicitFunctionParser extends Parser { + public static final Parser parser=new ImplicitFunctionParser(); + + private ImplicitFunctionParser() {} + + public Object parse(String str, int pos[]) throws ParseException { + int pos0=pos[0]; + String name; + Generic a[]; + int b[]; + List l=new ArrayList(); + try { + name=(String)CompoundIdentifier.parser.parse(str,pos); + } catch (ParseException e) { + pos[0]=pos0; + throw e; + } + while(true) { + try { + Generic s=(Generic)Subscript.parser.parse(str,pos); + l.add(s); + } catch (ParseException e) { + break; + } + } + try { + b=(int [])Derivation.parser.parse(str,pos); + } catch (ParseException e) { + b=new int[0]; + } + try { + a=(Generic[])ParameterList.parser.parse(str,pos); + } catch (ParseException e) { + pos[0]=pos0; + throw e; + } + Generic s[]=(Generic[])ArrayUtils.toArray(l,new Generic[l.size()]); + int derivation[]=new int[a.length]; + for(int i=0;i2?a[2]:a[1],a.length>3?a[3]:JSCLInteger.valueOf(1)); + else if(name.compareTo("grad")==0) v=new Grad(a[0],a[1]); + else if(name.compareTo("diverg")==0) v=new Divergence(a[0],a[1]); + else if(name.compareTo("curl")==0) v=new Curl(a[0],a[1]); + else if(name.compareTo("jacobian")==0) v=new Jacobian(a[0],a[1]); + else if(name.compareTo("laplacian")==0) v=new Laplacian(a[0],a[1]); + else if(name.compareTo("dalembertian")==0) v=new Dalembertian(a[0],a[1]); + else if(name.compareTo("del")==0) v=new Del(a[0],a[1],a.length>2?a[2]:JSCLInteger.valueOf(0)); + else if(name.compareTo("vector")==0) v=new VectorProduct(a[0],a[1]); + else if(name.compareTo("complex")==0) v=new ComplexProduct(a[0],a[1]); + else if(name.compareTo("quaternion")==0) v=new QuaternionProduct(a[0],a[1]); + else if(name.compareTo("geometric")==0) v=new GeometricProduct(a[0],a[1],a.length>2?a[2]:JSCLInteger.valueOf(0)); + else if(name.compareTo("matrix")==0) v=new MatrixProduct(a[0],a[1]); + else if(name.compareTo("tensor")==0) v=new TensorProduct(a[0],a[1]); + else if(name.compareTo("tran")==0) v=new Transpose(a[0]); + else if(name.compareTo("trace")==0) v=new Trace(a[0]); + else if(name.compareTo("det")==0) v=new Determinant(a[0]); + else if(name.compareTo("coef")==0) v=new Coefficient(a[0],a[1]); + else if(name.compareTo("solve")==0) v=new Solve(a[0],a[1],a.length>2?a[2]:JSCLInteger.valueOf(0)); + else if(name.compareTo("subst")==0) v=new Substitute(a[0],a[1],a[2]).transmute(); + else if(name.compareTo("lim")==0) v=new Limit(a[0],a[1],a[2],a.length>3 && (a[2].compareTo(Constant.infinity)!=0 && a[2].compareTo(Constant.infinity.negate())!=0)?JSCLInteger.valueOf(a[3].signum()):JSCLInteger.valueOf(0)); + else if(name.compareTo("sum")==0) v=new Sum(a[0],a[1],a[2],a[3]); + else if(name.compareTo("prod")==0) v=new Product(a[0],a[1],a[2],a[3]); + else if(name.compareTo("integral")==0) v=a.length>2?(Operator)new Integral(a[0],a[1],a[2],a[3]):new IndefiniteIntegral(a[0],a[1]); + else if(name.compareTo("groebner")==0) v=new Groebner(a[0],a[1],a.length>2?a[2]:Expression.valueOf("lex"),a.length>3?a[3]:JSCLInteger.valueOf(0)).transmute(); + else if(name.compareTo("div")==0) v=new Division(a[0],a[1]); + else if(name.compareTo("mod")==0) v=new Modulo(a[0],a[1]); + else if(name.compareTo("modpow")==0) v=new ModPow(a[0],a[1],a[2]); + else if(name.compareTo("modinv")==0) v=new ModInverse(a[0],a[1]); + else if(name.compareTo("eulerphi")==0) v=new EulerPhi(a[0]); + else if(name.compareTo("primitiveroots")==0) v=new PrimitiveRoots(a[0]); + return v; + } + + static boolean valid(String name) { + for(int i=0;ico2.length) return 1; + for(int i=co1.length-1;i>=0;i--) { + if(co1[i].compareTo(co2[i])<0) return -1; + else if(co1[i].compareTo(co2[i])>0) return 1; + } + return 0; + } + + public int compare(Object o1, Object o2) { + return compare((Comparable[])o1,(Comparable[])o2); + } +} diff --git a/src/misc/src/jscl/util/ArrayUtils.java b/src/misc/src/jscl/util/ArrayUtils.java new file mode 100644 index 00000000..78cf21a5 --- /dev/null +++ b/src/misc/src/jscl/util/ArrayUtils.java @@ -0,0 +1,112 @@ +package jscl.util; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.RandomAccess; + +public class ArrayUtils { + private ArrayUtils() {} + + public static Object[] concat(Object o1[], Object o2[], Object res[]) { + System.arraycopy(o1,0,res,0,o1.length); + System.arraycopy(o2,0,res,o1.length,o2.length); + return res; + } + + public static Object[] toArray(List list, Object res[]) { +// return list.toArray(res); + int n=list.size(); + for(int i=0;i> 1; + Object midVal = list.get(mid); + int cmp = ((Comparable)midVal).compareTo(key); + + if (cmp < 0) + low = mid + 1; + else if (cmp > 0) + high = mid - 1; + else + return mid; // key found + } + return -(low + 1); // key not found + } + + private static int iteratorBinarySearch(List list, Object key) { + int low = 0; + int high = list.size()-1; + ListIterator i = list.listIterator(); + + while (low <= high) { + int mid = (low + high) >> 1; + Object midVal = get(i, mid); + int cmp = ((Comparable)midVal).compareTo(key); + + if (cmp < 0) + low = mid + 1; + else if (cmp > 0) + high = mid - 1; + else + return mid; // key found + } + return -(low + 1); // key not found + } + + private static Object get(ListIterator i, int index) { + Object obj = null; + int pos = i.nextIndex(); + if (pos <= index) { + do { + obj = i.next(); + } while (pos++ < index); + } else { + do { + obj = i.previous(); + } while (--pos > index); + } + return obj; + } +}