formula parser now understands complex numbers, and some extra functions including let(x=2, x*x)

This commit is contained in:
Zeno Rogue 2018-11-07 00:51:41 +01:00
parent 7e80be5a87
commit 55fdd25a6c
5 changed files with 63 additions and 31 deletions

View File

@ -13,7 +13,7 @@ namespace polygonal {
typedef long double xld;
typedef complex<xld> cld;
typedef complex<xld> cxld;
int SI = 4;
ld STAR = 0;
@ -23,13 +23,13 @@ namespace polygonal {
precise matrix[MSI][MSI];
precise ans[MSI];
cld coef[MSI];
cxld coef[MSI];
ld coefr[MSI], coefi[MSI];
int maxcoef, coefid;
void solve() {
if(pmodel == mdPolynomial) {
for(int i=0; i<MSI; i++) coef[i] = cld(coefr[i], coefi[i]);
for(int i=0; i<MSI; i++) coef[i] = cxld(coefr[i], coefi[i]);
return;
}
if(pmodel != mdPolygonal) return;
@ -74,15 +74,15 @@ namespace polygonal {
y /= r;
}
if(pmodel == mdPolynomial) {
cld z(x,y);
cld res (0,0);
cxld z(x,y);
cxld res (0,0);
for(int i=maxcoef; i>=0; i--) { res += coef[i]; if(i) res *= z; }
return make_pair(real(res), imag(res));
}
cld z(x, y);
cld res (0,0);
cld zp = 1; for(int i=0; i<SI; i++) zp *= z;
cxld z(x, y);
cxld res (0,0);
cxld zp = 1; for(int i=0; i<SI; i++) zp *= z;
for(int i=prec; i>0; i--) {
res += ans[i];
@ -104,7 +104,7 @@ namespace polygonal {
else C = cos(ho * M_PI/180), S = sin(ho * M_PI / 180);
for(int r=0; r<=2000; r++) {
cld z = exp(cld(0, 2*M_PI * r / 2000.0));
cxld z = exp(cxld(0, 2*M_PI * r / 2000.0));
pair<xld,xld> z2 = compute(real(z), imag(z), deg);
hyperpoint h;
h[0] = (z2.first * C - z2.second * S) * vid.radius;
@ -123,7 +123,7 @@ namespace polygonal {
namespace spiral {
typedef long double ld;
typedef complex<long double> cld;
typedef complex<long double> cxld;
int shiftx, shifty, velx, vely;
@ -154,9 +154,9 @@ namespace spiral {
ld k = -2*M_PI*M_PI / log(2.6180339);
// cld mnoznik = cld(0, M_PI) / cld(k, M_PI);
// cxld mnoznik = cxld(0, M_PI) / cxld(k, M_PI);
cld factor = cld(0, -CY/2/M_PI/M_PI) * cld(k, M_PI);
cxld factor = cxld(0, -CY/2/M_PI/M_PI) * cxld(k, M_PI);
Yshift = CY * k / M_PI;
@ -167,8 +167,8 @@ namespace spiral {
for(int y=0; y<SY; y++)
for(int x=0; x<SX; x++) {
cld z(x-xc, y-yc);
cld z1 = log(z);
cxld z(x-xc, y-yc);
cxld z1 = log(z);
z1 = z1 * factor;

View File

@ -605,7 +605,7 @@ namespace dialog {
if(kind == 's') {
exp_parser ep;
ep.s = ne.s;
ld x = ep.parse();
ld x = real(ep.parse());
if(!ep.ok()) return;
if(ne.sc.positive && x <= 0) return;
*ne.editwhat = x;

13
hyper.h
View File

@ -167,6 +167,8 @@ typedef long double ld;
#define PLDF "Lf"
#endif
typedef complex<ld> cld;
#define DEBMEM(x) // { x fflush(stdout); }
#define DEBSM(x)
@ -4260,7 +4262,7 @@ struct exp_parser {
int at;
exp_parser() { at = 0; }
map<string, ld> extra_params;
map<string, cld> extra_params;
bool ok() { return at == isize(s); }
char next() { if(at == isize(s) || at == -1) return 0; else return s[at]; }
@ -4273,14 +4275,15 @@ struct exp_parser {
return false;
}
ld parse(int prio = 0);
cld parse(int prio = 0);
ld parsepar() {
ld res = parse();
cld parsepar() {
cld res = parse();
if(next() != ')') { at = -1; return res; }
at++;
return res;
}
}
};
#ifdef CAP_COMPLEX2

View File

@ -285,6 +285,12 @@ hyperpoint err = hpxyz(500,0,0);
bool iserror(hyperpoint h) { return sqhypot2(h) > 10000 || std::isnan(h[0]) || std::isnan(h[1]) || std::isnan(h[2]) || std::isinf(h[0]) || std::isinf(h[1]) || std::isinf(h[2]); }
hyperpoint xy_to_point(ld x, ld y) {
if(sphere && hypot(x, y) > 1)
return err;
return hpxy(x, y);
}
hyperpoint find_point(ld t) {
exp_parser ep;
auto &dict = ep.extra_params;
@ -298,17 +304,18 @@ hyperpoint find_point(ld t) {
ep.at = 0;
while(!among(ep.next(), '=', -1)) varname += ep.next(), ep.at++;
ep.at++;
ld x = ep.parse();
cld x = ep.parse();
if(!ep.ok()) return err;
dict[varname] = x;
}
if(!dict.count("y") && dict.count("r"))
return xspinpush0(dict["phi"], dict["r"]);
if(dict.count("z"))
return hpxyz(dict["x"], dict["y"], dict["z"]);
if(sphere && hypot(dict["x"], dict["y"]) > 1)
return err;
return hpxy(dict["x"], dict["y"]);
return xspinpush0(real(dict["phi"]), real(dict["r"]));
if(dict.count("z") && dict.count("x"))
return hpxyz(real(dict["x"]), real(dict["y"]), real(dict["z"]));
if(dict.count("z")) {
return xy_to_point(real(dict["z"]), imag(dict["z"]));
}
return xy_to_point(real(dict["x"]), real(dict["y"]));
}
hyperpoint gcurvestart = err;

View File

@ -151,8 +151,9 @@ struct indenter {
void doindent() { for(int i=0; i<current_indentation; i++) printf(" "); }
ld exp_parser::parse(int prio) {
ld res;
cld exp_parser::parse(int prio) {
cld res;
while(next() == ' ') at++;
if(eat("sin(")) res = sin(parsepar());
else if(eat("cos(")) res = cos(parsepar());
else if(eat("sinh(")) res = sinh(parsepar());
@ -167,7 +168,27 @@ ld exp_parser::parse(int prio) {
else if(eat("tanh(")) res = tanh(parsepar());
else if(eat("atan(")) res = atan(parsepar());
else if(eat("atanh(")) res = atanh(parsepar());
else if(next() == '(') at++, res = parsepar();
else if(eat("abs(")) res = abs(parsepar());
else if(eat("re(")) res = real(parsepar());
else if(eat("im(")) res = imag(parsepar());
else if(eat("conj(")) res = std::conj(parsepar());
else if(eat("let(")) {
string name;
while(true) {
char c = next();
if((c >= '0' && c <= '9') || c == '.' || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_')
name += c, at++;
else break;
}
if(next() != '=') { at = -1; return 0; }
at++;
cld val = parse(0);
if(next() != ',') { at = -1; return 0; }
at++;
dynamicval<cld> d(extra_params[name], val);
return parsepar();
}
else if(next() == '(') at++, res = parsepar();
else {
string number;
while(true) {
@ -177,6 +198,7 @@ ld exp_parser::parse(int prio) {
else break;
}
if(number == "e") res = exp(1);
else if(number == "i") res = cld(0, 1);
else if(number == "p" || number == "pi") res = M_PI;
else if(number == "" && next() == '-') res = 0, prio = 0;
else if(number == "") at = -1;
@ -198,7 +220,7 @@ ld exp_parser::parse(int prio) {
ld parseld(const string& s) {
exp_parser ep;
ep.s = s;
return ep.parse();
return real(ep.parse());
}
}