package fplot;
import java.util.*;
/**
* Die Knoten des Syntaxbaumes.
* @author Christian Semrau
*
* Christian.Semrau@student.uni-magdeburg.de
*
Homepage
*/
class FuncNode extends NodeBase {
// Operator
private int op;
// Funktion
private int func;
// Zahlenwert
private double val;
// Unterknotenliste: {left, ..., right}
private FuncNode[] nodes;
// Laenge der Unterknotenliste
private int nlen;
// Unterknoten klammern:
// [WENIG,MITTEL,ALLES][left,...,right][oeffnen,schliessen]
private String[][][] par;
// Klammerungsstufe
private int klammerung = KLAMMERUNG_MITTEL;
/** Zufallszahlengenerator */
private static Random rnd = new Random();
/** Konstruiert einen neuen Knoten ohne Unterknoten */
FuncNode(int oper, int func, double value) {
this(oper, func, value, null, null);
}
/** Konstruiert einen neuen Knoten */
FuncNode(int oper, int func, double value, FuncNode l, FuncNode r) {
this.op = oper;
this.func = func;
this.val = value;
this.nodes = new FuncNode[]{l, r};
this.nlen = 2;
calcPara();
}
/** Konstruiert einen neuen Knoten */
FuncNode(int oper, int func, double value, FuncNode[] subnodes) {
this.op = oper;
this.func = func;
this.val = value;
if (subnodes == null || subnodes.length == 0)
this.nodes = new FuncNode[]{null, null};
else
if (subnodes.length == 1)
this.nodes = new FuncNode[]{subnodes[0], null};
else
this.nodes = (FuncNode[])subnodes.clone();
this.nlen = nodes.length;
calcPara();
}
/** Liefert den linken Unterknoten */
public FuncNode left() {
return nodes[0];
}
/** Liefert den rechten Unterknoten */
public FuncNode right() {
return nodes[nlen-1];
}
/**
*
*/
protected void calcPara() {
if(op==FUNC0 || op==FUNC1 || op==FUNC2 || op==FUNC3) {
final int W = 0, M = 1, A = 2;
// [W,M,A][links,...,rechts]
boolean[][] kl = new boolean[3][nlen];
for (int n=0; n=0)){
kl[A][L] = false; kl[M][L] = false; kl[W][L] = false;
}else{
kl[A][L] = true;
if (lop==FUNC0 || lop==FUNC1 || lop==FUNC2 || lop==FUNC3
|| (isOp(op) && prioritaet(op)==prioritaet(lop))
|| op==ADD){
kl[M][L] = false;
kl[W][L] = false;
}else{
kl[M][L] = true;
kl[W][L] = prioritaet(op)>=prioritaet(lop);
}
}
if (right()==null || isConst(rop = right().op)
|| (rop==ZAHL && right().val>=0)){
kl[A][R] = false; kl[M][R] = false; kl[W][R] = false;
}else{
kl[A][R] = true;
if (rop==FUNC0 || rop==FUNC1 || rop==FUNC2 || rop==FUNC3
|| (isOp(op) && prioritaet(op)==prioritaet(rop) && assoziativ(op))
|| op==ADD){
kl[M][R] = false;
kl[W][R] = false;
}else{
kl[M][R] = true;
kl[W][R] = prioritaet(op)>=prioritaet(rop);
}
}
// [W,M,A][links,rechts][oeffnen,schliessen]
par = new String[3][2][2];
for(int stufe=0; stufe<3; stufe++)
for(int lr=0; lr<2; lr++){
if (kl[stufe][lr]){
par[stufe][lr][0] = "(";
par[stufe][lr][1] = ")";
}else{
par[stufe][lr][0] = "";
par[stufe][lr][1] = "";
}
}
}
}
/** Wertet die Funktion des Knoten aus.
* Wird von evalFunc(double[]) aufgerufen. */
protected double evalFunc(double v1, double v2) {
switch(func){
// FUNC0
case RND: return Math.random();
case RNDN: return rnd.nextGaussian();
// FUNC1
case SIN: return Math.sin(v1);
case COS: return Math.cos(v1);
case TAN: return Math.tan(v1);
case COT: return Math.tan(Math.PI/2-v1);
case ASIN: return Math.asin(v1);
case ACOS: return Math.acos(v1);
case ATAN: return Math.atan(v1);
case ACOT: return Math.PI/2-Math.atan(v1);
case SINH: return (Math.exp(v1)-Math.exp(-v1))/2;
case COSH: return (Math.exp(v1)+Math.exp(-v1))/2;
case TANH: return (Math.exp(v1)-Math.exp(-v1))/(Math.exp(v1)+Math.exp(-v1));
case COTH: return (Math.exp(v1)+Math.exp(-v1))/(Math.exp(v1)-Math.exp(-v1));
case ARSINH: return Math.log(v1+Math.sqrt(v1*v1+1));
case ARCOSH: return Math.log(v1+Math.sqrt(v1*v1-1));
case ARTANH: return Math.log(Math.sqrt((1+v1)/(1-v1)));
case ARCOTH: return Math.log(Math.sqrt((v1+1)/(v1-1)));
case ABS: return Math.abs(v1);
case SGN: return (v1>0)?+1:(v1<0)?-1:0;
case INV: return 1/v1;
case INT: return Math.floor(v1);
case FRAC: return v1-Math.floor(v1);
case SQR: return v1*v1;
case SQRT: return Math.sqrt(v1);
case FAC: return fakd((int)v1);
case GAMMA: return gamma(v1);
case EXP: return Math.exp(v1);
case LN: return Math.log(v1);
case LG: return Math.log(v1)/Math.log(10);
case LD: return Math.log(v1)/Math.log(2);
// FUNC2
case LOG: return Math.log(v2)/Math.log(v1);
case POW: return Math.pow(v1,v2);
case ROOT:
if (v2==(int)v2 && ((int)v2%2==1) && v1<0)
// ganzzahlige ungerade Wurzel und negativer Radikand
return -Math.pow(-v1,1/v2);
else
return Math.pow(v1,1/v2);
case MPOW: {
int index = (int)v2;
if (index==0) return 1;
else if (index<0) return 0;
double ret = v1;
for (int i=1; i=1 ? v[0] : 0;
double v2 = v.length>=2 ? v[1] : 0;
double v3 = v.length>=3 ? v[2] : 0;
switch(func){
case SUM: return 0;
// wird bereits von evaluate(double,double,double,int) ausgewertet
case SUM3: return 0;
// wird bereits von evaluate(double,double,double,int) ausgewertet
case IF: return 0;
// wird bereits von evaluate(double,double,double,int) ausgewertet
default: return evalFunc(v1, v2);
}
}
/** Wertet den Knoten aus mit dem gegebenen Wert fuer x */
public double evaluate(double x) {
return evaluate(x, 0, 0, 0);
}
/** Wertet den Knoten aus mit den gegebenen Werten fuer x,p,q und i */
public double evaluate(double x, double p, double q, int ci) {
double s;
// Sonderbehandlung fuer sum(grenze, ausdruck)
if (op==FUNC2 && func==SUM){
if (right()==null) return 0;
double le = left()!=null ? left().evaluate(x, p, q, ci) : 0;
s = 0;
int index = (int)le;
for(int i=1; i<=index; i++)
s+= right().evaluate(x, p, q, i);
return s;
}
// Sonderbehandlung fuer sum3(anfang, ende, ausdruck)
if (op==FUNC3 && func==SUM3){
if (right()==null) return 0;
double anf = nodes[0]!=null ? nodes[0].evaluate(x, p, q, ci) : 0;
double ende = nodes[1]!=null ? nodes[1].evaluate(x, p, q, ci) : 0;
s = 0;
int Anf = (int)anf;
int Ende = (int)ende;
for(int i=Anf; i<=Ende; i++)
s+= right().evaluate(x, p, q, i);
return s;
}
// Sonderbehandlung fuer IF(bedingung, wert1, wert2)
if (op==FUNC3 && func==IF){
double bedingung, wert;
bedingung = nodes[0]!=null ? nodes[0].evaluate(x, p, q, ci) : 0;
if (bedingung>0)
wert = nodes[1]!=null ? nodes[1].evaluate(x, p, q, ci) : 0;
else
wert = nodes[2]!=null ? nodes[2].evaluate(x, p, q, ci) : 0;
return wert;
}
double[] v = new double[nodes.length];
double le;
double ri;
for (int i=0; i