home *** CD-ROM | disk | FTP | other *** search
- /*
- Funktionsplotter in Storm C
-
- Function-Modul
-
- */
-
- #include <iostream.h>
- #include <stdio.h>
- #include <math.h>
- #include <stdlib.h>
- #include <ctype.h>
-
- #include "fclass.h"
-
- // Destruktoren:
-
- Func::~Func() { } // Default: garnix
-
- UnOpN::~UnOpN()
- { delete arg; }
-
- BinOpN::~BinOpN()
- { delete l;
- delete r;
- }
-
- // Konstruktoren:
-
- double Func::Dummy;
-
- KonstN::KonstN (double c)
- { Konst = c; }
-
- UnOpN::UnOpN(UnOps op, Func *n):
- oper(op), arg(n)
- { }
-
- BinOpN::BinOpN(BinOps op, Func *ln, Func *rn):
- oper(op), l(ln), r(rn)
- { }
-
- // "Konstant"-Funktionen:
-
- int Func::isconst (double &retval)
- { return 0; }
-
- int KonstN::isconst (double &retval)
- { retval = Konst;
- return 1;
- }
-
- // Ausgabe
-
- #define EPANIC 26731
-
- void KonstN::print(char*)
- {
- printf("%g", Konst);
- }
-
- void VarN::print(char*)
- { printf("x"); }
-
- void ErrorN::print(char*)
- { printf("?"); }
-
- void UnOpN::print(char* str)
- { switch(oper)
- { case Op_neg: printf("-"); break;
- case Op_sqr: printf("sqr "); break;
- case Op_sqrt: printf("sqrt "); break;
- case Op_sin: printf("sin "); break;
- case Op_cos: printf("cos "); break;
- case Op_exp: printf("exp "); break;
- case Op_ln: printf("ln "); break;
- }
- arg->print(str);
- }
-
- void BinOpN::print(char* str)
- { printf("(");
- l->print(str);
- switch (oper)
- { case Op_add: printf("+"); break;
- case Op_sub: printf("-"); break;
- case Op_mult:printf("*"); break;
- case Op_div: printf("/"); break;
- case Op_pot: printf("^"); break;
- default: exit(EPANIC);
- }
- r->print(str);
- printf(")");
- }
-
- // Auswertung
-
- inline double sqr(double x)
- { return x*x; }
-
- double intpotz(double base, int exp)
- { if (exp)
- { if (exp<0) return 1.0/intpotz(base,-exp)
- else if (exp==1) return base;
- else if (exp&1) return base*sqr(intpotz(base, exp/2));
- else return sqr(intpotz(base, exp/2));
- }
- else return 1;
- }
-
- double UnOpN::eval (double x)
- {
- double y = arg->eval(x);
-
- switch(oper)
- { case Op_neg: return -y;
- case Op_sqr: return y*y;
- case Op_sqrt: return sqrt(y);
- case Op_sin: return sin(y);
- case Op_cos: return cos(y);
- case Op_exp: return exp(y);
- case Op_ln: return log(y);
- default: exit(EPANIC);
- }
- }
-
- double BinOpN::eval (double x)
- { double lv = l->eval(x), rv = r->eval(x);
- switch(oper)
- { case Op_add: return lv+rv;
- case Op_sub: return lv-rv;
- case Op_mult: return lv*rv;
- case Op_div: return lv/rv;
- case Op_pot: if (r->isconst() && floor(rv)==rv)
- return intpotz(lv, int(rv))
- else if (lv > 0) return exp(rv*log(lv));
- return 0;
- default: exit(EPANIC);
- }
- }
-
-
- // ******** Parsing ********
-
- #define EULER 2.7182818284
- #define PI 3.141592653589
-
- char *cp; // Zeiger auf String
- char c; // gescanntes Zeichen
- short ErrFlag; // Fehler aufgetreten?
-
-
- char Get()
- { while ((c = *cp) == ' ')
- cp++;
- if(c) cp++;
- return c;
- }
-
- Func *Fehler()
- { if (!ErrFlag)
- { cout << "\nError.\n";
- ErrFlag = 1;
- }
- return new ErrorN;
- }
-
- Func *Expression();
-
- Func *Term();
-
- Func *Potenz();
-
- Func *Factor()
- { while (c=='+') Get();
-
- if (c=='x' || c=='X')
- { Get();
- return new VarN;
- }
- else if (c >= '0' && c <= '9')
- {
- int i = 0;
- enum {max = 80};
- char numstr[max+1];
-
- while (isdigit(c) && i<max)
- { numstr[i++] = c; Get(); }
-
- if (c=='.')
- { numstr[i++] = c; Get(); }
- while (isdigit(c) && i<max)
- { numstr[i++] = c; Get(); }
-
- if (tolower(c)=='e')
- { numstr[i++] = c; Get();
-
- if (c=='+' || c=='-')
- { numstr[i++] = c; Get(); }
- else
- if (!isdigit(c))
- return Fehler();
-
- while (isdigit(c) && i<max)
- { numstr[i++] = c; Get(); }
-
- }
-
- numstr[i]=0;
- return new KonstN(atof(numstr));
- }
- else
- if (c=='(')
- { Get();
- Func *np = Expression();
- if (c==')')
- Get();
- else
- delete Fehler();
- return np;
- }
- else
- if (c=='c')
- { if (Get()=='o' && Get() == 's')
- { Get(); return new UnOpN(Op_cos, Factor()); }
- else
- return Fehler();
- }
- else
- if (c=='e')
- { if (Get()!='x')
- return new KonstN(EULER);
- else if (Get() == 'p')
- { Get(); return new UnOpN(Op_exp, Factor()); }
- else
- return Fehler();
- }
- else if (c=='l')
- { if (Get()=='n')
- return Get(), new UnOpN(Op_ln, Factor());
- else
- return Fehler();
- }
- else if (c=='p')
- { if (Get()!='i')
- return Fehler();
- Get(); return new KonstN(PI);
- }
- else if (c=='s')
- { Get();
- if (c=='i')
- { if (Get() != 'n') return Fehler();
- Get();
- return new UnOpN(Op_sin, Factor());
- }
- else if (c=='q')
- { if (Get() != 'r') return Fehler();
- if (Get()=='t')
- { Get();
- return new UnOpN(Op_sqrt, Factor());
- }
- else return new UnOpN(Op_sqr, Factor());
- }
- else
- return Fehler();
- }
-
- // Default-Ergebnis:
- return Fehler();
- }
-
- Func *Potenz()
- {
- Func *n1 = Factor();
-
- while (c=='^')
- { Get();
- Func *n2 = Factor();
- n1 = new BinOpN(Op_pot, n1, n2);
- }
- return n1;
- }
-
- Func *Term()
- { Func *n1 = Potenz();
-
- while (c=='*' || c=='/')
- { BinOps op = c=='*'? Op_mult : Op_div;
- Get();
- Func *n2 = Potenz();
- n1 = new BinOpN(op, n1, n2);
- }
- return n1;
- }
-
- Func *Expression()
- {
- if (c=='-')
- { Get();
- Func *np = Term();
- return new UnOpN(Op_neg,np);
- }
- else
- { Func *n1 = Term();
- while (c=='+' || c=='-')
- { BinOps op = c=='+'? Op_add : Op_sub;
- Get();
- Func *n2 = Term();
- n1 = new BinOpN(op, n1, n2);
- }
- return n1;
- }
- }
-
- Func *Parse(char *string)
- { cp = string;
- ErrFlag = 0;
-
- Get();
- Func *expr = Expression();
- if (c) delete Fehler();
-
- if(ErrFlag)
- { delete expr; return 0; }
- else
- return expr;
- }
-
-
-