1
0
mirror of https://github.com/zenorogue/hyperrogue.git synced 2024-12-24 17:10:36 +00:00

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

View File

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

13
hyper.h
View File

@ -167,6 +167,8 @@ typedef long double ld;
#define PLDF "Lf" #define PLDF "Lf"
#endif #endif
typedef complex<ld> cld;
#define DEBMEM(x) // { x fflush(stdout); } #define DEBMEM(x) // { x fflush(stdout); }
#define DEBSM(x) #define DEBSM(x)
@ -4260,7 +4262,7 @@ struct exp_parser {
int at; int at;
exp_parser() { at = 0; } exp_parser() { at = 0; }
map<string, ld> extra_params; map<string, cld> extra_params;
bool ok() { return at == isize(s); } bool ok() { return at == isize(s); }
char next() { if(at == isize(s) || at == -1) return 0; else return s[at]; } char next() { if(at == isize(s) || at == -1) return 0; else return s[at]; }
@ -4273,14 +4275,15 @@ struct exp_parser {
return false; return false;
} }
ld parse(int prio = 0); cld parse(int prio = 0);
ld parsepar() { cld parsepar() {
ld res = parse(); cld res = parse();
if(next() != ')') { at = -1; return res; } if(next() != ')') { at = -1; return res; }
at++; at++;
return res; return res;
} }
}; };
#ifdef CAP_COMPLEX2 #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]); } 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) { hyperpoint find_point(ld t) {
exp_parser ep; exp_parser ep;
auto &dict = ep.extra_params; auto &dict = ep.extra_params;
@ -298,17 +304,18 @@ hyperpoint find_point(ld t) {
ep.at = 0; ep.at = 0;
while(!among(ep.next(), '=', -1)) varname += ep.next(), ep.at++; while(!among(ep.next(), '=', -1)) varname += ep.next(), ep.at++;
ep.at++; ep.at++;
ld x = ep.parse(); cld x = ep.parse();
if(!ep.ok()) return err; if(!ep.ok()) return err;
dict[varname] = x; dict[varname] = x;
} }
if(!dict.count("y") && dict.count("r")) if(!dict.count("y") && dict.count("r"))
return xspinpush0(dict["phi"], dict["r"]); return xspinpush0(real(dict["phi"]), real(dict["r"]));
if(dict.count("z")) if(dict.count("z") && dict.count("x"))
return hpxyz(dict["x"], dict["y"], dict["z"]); return hpxyz(real(dict["x"]), real(dict["y"]), real(dict["z"]));
if(sphere && hypot(dict["x"], dict["y"]) > 1) if(dict.count("z")) {
return err; return xy_to_point(real(dict["z"]), imag(dict["z"]));
return hpxy(dict["x"], dict["y"]); }
return xy_to_point(real(dict["x"]), real(dict["y"]));
} }
hyperpoint gcurvestart = err; hyperpoint gcurvestart = err;

View File

@ -151,8 +151,9 @@ struct indenter {
void doindent() { for(int i=0; i<current_indentation; i++) printf(" "); } void doindent() { for(int i=0; i<current_indentation; i++) printf(" "); }
ld exp_parser::parse(int prio) { cld exp_parser::parse(int prio) {
ld res; cld res;
while(next() == ' ') at++;
if(eat("sin(")) res = sin(parsepar()); if(eat("sin(")) res = sin(parsepar());
else if(eat("cos(")) res = cos(parsepar()); else if(eat("cos(")) res = cos(parsepar());
else if(eat("sinh(")) res = sinh(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("tanh(")) res = tanh(parsepar());
else if(eat("atan(")) res = atan(parsepar()); else if(eat("atan(")) res = atan(parsepar());
else if(eat("atanh(")) res = atanh(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 { else {
string number; string number;
while(true) { while(true) {
@ -177,6 +198,7 @@ ld exp_parser::parse(int prio) {
else break; else break;
} }
if(number == "e") res = exp(1); 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 == "p" || number == "pi") res = M_PI;
else if(number == "" && next() == '-') res = 0, prio = 0; else if(number == "" && next() == '-') res = 0, prio = 0;
else if(number == "") at = -1; else if(number == "") at = -1;
@ -198,7 +220,7 @@ ld exp_parser::parse(int prio) {
ld parseld(const string& s) { ld parseld(const string& s) {
exp_parser ep; exp_parser ep;
ep.s = s; ep.s = s;
return ep.parse(); return real(ep.parse());
} }
} }