package jasymca; /* Jasymca - - Symbolic Calculator for Mobile Devices This version is written for J2ME, CLDC 1.1, MIDP 2, JSR 75 or J2SE Copyright (C) 2006 - Helmut Dersch der@hs-furtwangen.de This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /*------------------------------------------------------------*/ import java.util.Vector; public class Polynomial extends Algebraic{ public Algebraic[] coef = null; public Variable var = null; // Polynomial with main-est Variable public static Polynomial top = new Polynomial(SimpleVariable.top); public Polynomial(){} public Polynomial(Variable var, Algebraic[] coef){ this.var = var; this.coef = norm(coef); } public Polynomial(Variable var){ coef = new Zahl[2]; coef[0] = Zahl.ZERO; coef[1] = Zahl.ONE; this.var= var; } // Remove leading Zero coefficients,, leave coef[0] public Algebraic[] norm(Algebraic[] x){ int len = x.length; while(len>0 && (x[len-1]==null || x[len-1].equals(Zahl.ZERO))){ len--; } if(len == 0) len = 1; if(len!=x.length){ Algebraic[] na= new Algebraic[len]; for(int i=0; i=0; i--,k--){ cdiv[i] = nom[k].div( den); nom[k] = Zahl.ZERO; for(int j=k-1,l=q.coef.length-2; j>k-q.coef.length; j--,l--) nom[j] = nom[j].sub( cdiv[i].mult(q.coef[l])); } // Sowohl r[0] als auch r[1] können Rational sein, allerdings // ohne von var abhängigem Nenner result[0] = horner(var,cdiv); result[1] = horner(var,nom,nom.length-1 -len); return result; } // The larger of the two variables is assumed to be main else if( q.var.smaller(var) ){ // var is main, q is independ of var Algebraic[] cn = new Algebraic[coef.length]; for(int i=0; i0) r = r.add(coef[0].reduce()); return r;*/ } public Algebraic[] clone(Algebraic[] x){ Algebraic[] c = new Algebraic[x.length]; for(int i=0; i0;i--){ if( coef[i].equals(Zahl.ZERO) ) continue; String s = ""; if(coef[i].equals(Zahl.MINUS)) s+="-"; else if( !coef[i].equals(Zahl.ONE) ) s+=coef[i].toString()+"*"; s+=var.toString(); if(i>1) s+="^"+i; x.addElement(s); } if( !coef[0].equals(Zahl.ZERO) ) x.addElement(coef[0].toString()); String s = ""; if(x.size()>1) s+="("; for(int i=0; i1) s+=")"; return s; } public boolean equals(Object x){ if (! (x instanceof Polynomial) ) return false; if(!(var.equals(((Polynomial)x).var)) || coef.length != ((Polynomial)x).coef.length) return false; for(int i=0; i0; i--){ r = Lisp.list(Lisp.cons("*", Lisp.cons(x, r))); if(!coef[i-1].equals(Zahl.ZERO)){ r = Lisp.list(Lisp.cons("+", Lisp.cons(coef[i-1].toPrefix(), r))); } } return Lisp.car(r); } public Algebraic deriv( Variable var ) throws JasymcaException{ Algebraic r1 = Zahl.ZERO, r2 = Zahl.ZERO; Polynomial x = new Polynomial(this.var); for(int i=coef.length-1; i>1; i--){ // Horner r1 = r1.add(coef[i].mult(new Unexakt(i))).mult(x); // diff Variable } if(coef.length>1) r1 = r1.add(coef[1]); for(int i=coef.length-1; i>0; i--){ // Horner r2 = r2.add(coef[i].deriv(var)).mult(x); // diff coef } if(coef.length>0) r2 = r2.add(coef[0].deriv(var)); return r1.mult(this.var.deriv(var)).add(r2).reduce(); } // Coefficients do not depend on var public boolean constcoef(Variable var){ if(!var.equals(this.var)){ if((this.var instanceof FunctionVariable) && ((FunctionVariable)this.var).arg.depends(var)) return false; } for(int i=0; i0){ for(int k=0; k1/(n+1)*x^(n+1) in=in.add(coef[i].mult(new Polynomial(var).pow_n(i+1).div(new Unexakt(i+1)))); else if(this.var instanceof FunctionVariable && ((FunctionVariable)this.var).arg.depends(var)) // f(x) if(i==1) in=in.add( ((FunctionVariable)this.var).integrate(var).mult(coef[1])); // (f(x))^2, (f(x))^3 etc // give up here but try again after exponential normalization else throw new JasymcaException("Integral not supported."); else // Constant: c --> c*x in=in.add(coef[i].mult(new Polynomial(var).mult(new Polynomial(this.var).pow_n(i)))); else if(var.equals(this.var)) // c(x)*x^n , should not happen if this is canonical throw new JasymcaException("Integral not supported."); else if(this.var instanceof FunctionVariable && ((FunctionVariable)this.var).arg.depends(var)){ if(i==1 && coef[i] instanceof Polynomial && ((Polynomial)coef[i]).var.equals(var)){ // poly(x)*f(x) // First attempt: try to isolate inner derivative // poly(x)*f(w(x)) --> check poly(x)/w' == q : const? // yes --> Int f dw * q p("Trying to isolate inner derivative "+this); try{ FunctionVariable f = (FunctionVariable)this.var; Algebraic w = f.arg; // Innere Funktion Algebraic q = coef[i].div(w.deriv(var)); if(q.deriv(var).equals(Zahl.ZERO)){ // q - constant SimpleVariable v = new SimpleVariable("v"); Algebraic p = FunctionVariable.create(f.fname, new Polynomial(v)); Algebraic r = p.integrate(v).value(v,w).mult(q); in=in.add(r); continue; } }catch(JasymcaException je){ // Didn't work, try more methods } p("Failed."); // Some partial integrations follow. To // avoid endless loops, we flag this section // Coefficients of coef[i] must not depend on var for(int k=0;k<((Polynomial)coef[i]).coef.length;k++) if(((Polynomial)coef[i]).coef[k].depends(var)) throw new JasymcaException("Function not supported by this method"); if(loopPartial){ loopPartial = false; p("Partial Integration Loop detected."); throw new JasymcaException("Partial Integration Loop: "+this); } // First attempt: x^n*f(x) , n-times diff! // works for exp,sin,cos p("Trying partial integration: x^n*f(x) , n-times diff "+ this); try{ loopPartial=true; Algebraic p = coef[i]; Algebraic f = ((FunctionVariable)this.var).integrate(var); Algebraic r = f.mult(p); while(!(p=p.deriv(var)).equals(Zahl.ZERO)){ f = f.integrate(var).mult(Zahl.MINUS); r = r.add(f.mult(p)); } loopPartial=false; in=in.add(r); continue; }catch (JasymcaException je){ loopPartial=false; } p("Failed."); // Second attempt: x^n*f(x) , 1-times int! // works for log, atan p("Trying partial integration: x^n*f(x) , 1-times int "+ this); try{ loopPartial=true; Algebraic p = coef[i].integrate(var); Algebraic f = new Polynomial((FunctionVariable)this.var); Algebraic r = p.mult(f).sub(p.mult(f.deriv(var)).integrate(var)); loopPartial=false; in=in.add(r); continue; }catch(JasymcaException je3){ loopPartial=false; } p("Failed"); // Add more attempts.... throw new JasymcaException("Function not supported by this method"); }else throw new JasymcaException("Integral not supported."); }else // mainvar independend of var, treat as constant and integrate coef in=in.add(coef[i].integrate(var).mult(new Polynomial(this.var).pow_n(i))); } if(coef.length>0) in=in.add(coef[0].integrate(var)); return in; } public Algebraic cc() throws JasymcaException{ Polynomial xn = new Polynomial(var.cc()); Algebraic r = Zahl.ZERO; for(int i=coef.length-1; i>0; i--) r = r.add( coef[i].cc() ).mult(xn); if(coef.length>0) r = r.add(coef[0].cc()); return r; } // Evaluate Polynomial for var = x public Algebraic value(Variable var, Algebraic x) throws JasymcaException{ Algebraic r = Zahl.ZERO; Algebraic v = this.var.value(var,x); for(int i=coef.length-1; i>0; i--){ // Horner r = r.add(coef[i].value(var,x)).mult(v); } if(coef.length>0) r = r.add(coef[0].value(var,x)); return r; } public Algebraic value(Algebraic x) throws JasymcaException{ return value(this.var, x); } public double norm(){ double norm=0.; for(int i=0; i0; i--){ r=r.add(f.f_exakt(coef[i])).mult(x); } if(coef.length>0) r=r.add(f.f_exakt(coef[0])); return r; } ////////////////////////// Roots ///////////////////////////////////////////////////// // is var multiplicative variable (i.e. not contained inside // Functionvariable boolean dependsmult(Variable var) throws JasymcaException{ if(var.equals(this.var)) return true; for(int i=0; i top return ((Polynomial)value(var, top)).solve(SimpleVariable.top); Algebraic[] factors = square_free_dec(var); Vector s = new Vector(); int n = factors==null?0:factors.length; for(int i=0; ib!=0! static int gcd(int a, int b){ int c = 1; while(c!=0){ c = a % b; a = b; b = c; } return a; } // Use only for (a) constant coefficients and (b) squarefree function (c) monic polynomial // Adapted from c-code by C. Bond (1991) public Vektor bairstow() throws JasymcaException{ double[] a = new double[coef.length]; for(int i=0; i 2) { double r,s,dn,dr,ds,drn,dsn,eps; int i,iter; r = s = 0; dr = 1.0; ds = 0; eps = 1e-14; iter = 1; while ((Math.abs(dr)+Math.abs(ds)) > eps) { if ((iter % 200) == 0) { r=Math.random() * 1000; } if ((iter % 500) == 0) { eps*=10.0; } b[1] = a[1] - r; c[1] = b[1] - r; for (i=2;i<=n;i++){ b[i] = a[i] - r * b[i-1] - s * b[i-2]; c[i] = b[i] - r * c[i-1] - s * c[i-2]; } dn=c[n-1] * c[n-3] - c[n-2] * c[n-2]; drn=b[n] * c[n-3] - b[n-1] * c[n-2]; dsn=b[n-1] * c[n-1] - b[n] * c[n-2]; if (Math.abs(dn) < 1e-16) { dn = 1; drn = 1; dsn = 1; } dr = drn / dn; ds = dsn / dn; r += dr; s += ds; iter++; } for (i=0;i=2;i-=2) {/* quadratics */ Algebraic[] lsg = pqsolve(a[i-1],a[i]); result[k++] = lsg[0]; result[k++] = lsg[1]; } if ((n % 2) == 1) result[k] = new Unexakt(-a[1]); return new Vektor(result); } // solve x^2+px+q=0 static Zahl[] pqsolve(double p, double q){ Zahl r[] = new Zahl[2]; p = -p/2.; q = p*p-q; if(q>0){ q = Math.sqrt(q); r[0] = new Unexakt(p + q); r[1] = new Unexakt(p - q); }else if(q<0){ q = Math.sqrt(-q); r[0] = new Unexakt(p, q); r[1] = new Unexakt(p, -q); }else{ r[0] = new Unexakt(p); r[1] = r[0]; } return r; } }