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:
parent
7e80be5a87
commit
55fdd25a6c
@ -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;
|
||||||
|
|
||||||
|
@ -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
13
hyper.h
@ -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
|
||||||
|
@ -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;
|
||||||
|
30
util.cpp
30
util.cpp
@ -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());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user