From 55fdd25a6c7d3fce0cb7c7daa91290eaa17b6197 Mon Sep 17 00:00:00 2001 From: Zeno Rogue Date: Wed, 7 Nov 2018 00:51:41 +0100 Subject: [PATCH] formula parser now understands complex numbers, and some extra functions including let(x=2, x*x) --- conformal.cpp | 28 ++++++++++++++-------------- dialogs.cpp | 2 +- hyper.h | 13 ++++++++----- rogueviz-graph.cpp | 21 ++++++++++++++------- util.cpp | 30 ++++++++++++++++++++++++++---- 5 files changed, 63 insertions(+), 31 deletions(-) diff --git a/conformal.cpp b/conformal.cpp index ee2727a4..e6287e40 100644 --- a/conformal.cpp +++ b/conformal.cpp @@ -13,7 +13,7 @@ namespace polygonal { typedef long double xld; - typedef complex cld; + typedef complex 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=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; i0; 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 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 cld; + typedef complex 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 cld; + #define DEBMEM(x) // { x fflush(stdout); } #define DEBSM(x) @@ -4260,7 +4262,7 @@ struct exp_parser { int at; exp_parser() { at = 0; } - map extra_params; + map 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 diff --git a/rogueviz-graph.cpp b/rogueviz-graph.cpp index 4f49ca86..702ea6de 100644 --- a/rogueviz-graph.cpp +++ b/rogueviz-graph.cpp @@ -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; diff --git a/util.cpp b/util.cpp index 027ab916..16f840dc 100644 --- a/util.cpp +++ b/util.cpp @@ -151,8 +151,9 @@ struct indenter { void doindent() { for(int i=0; i= '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 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()); } }