2017-03-23 10:53:57 +00:00
|
|
|
// Hyperbolic Rogue
|
2018-02-08 23:40:26 +00:00
|
|
|
// Copyright (C) 2011-2018 Zeno Rogue, see 'hyper.cpp' for details
|
2017-03-23 10:53:57 +00:00
|
|
|
|
|
|
|
// basic utility functions
|
|
|
|
|
2018-06-10 23:58:31 +00:00
|
|
|
namespace hr {
|
|
|
|
|
2018-06-12 21:10:20 +00:00
|
|
|
#if CAP_TIMEOFDAY
|
|
|
|
#if !CAP_SDL
|
2018-07-23 03:16:16 +00:00
|
|
|
int lastusec;
|
|
|
|
int uticks;
|
|
|
|
|
2018-06-12 21:10:20 +00:00
|
|
|
int SDL_GetTicks() {
|
2018-07-23 03:16:16 +00:00
|
|
|
struct timeval tim;
|
|
|
|
gettimeofday(&tim, NULL);
|
|
|
|
int newusec = tim.tv_usec;
|
|
|
|
uticks += newusec - lastusec;
|
|
|
|
if(newusec <= lastusec)
|
|
|
|
uticks += 1000000;
|
|
|
|
lastusec = newusec;
|
|
|
|
return uticks / 1000;
|
2018-06-12 21:10:20 +00:00
|
|
|
}
|
2018-07-23 03:16:16 +00:00
|
|
|
|
2018-06-12 21:10:20 +00:00
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
2017-07-10 18:47:38 +00:00
|
|
|
long double sqr(long double x) { return x*x; }
|
2017-03-23 10:53:57 +00:00
|
|
|
string its(int i) { char buf[64]; sprintf(buf, "%d", i); return buf; }
|
|
|
|
string fts(float x) { char buf[64]; sprintf(buf, "%4.2f", x); return buf; }
|
|
|
|
string fts3(float x) { char buf[64]; sprintf(buf, "%5.3f", x); return buf; }
|
|
|
|
string fts4(float x) { char buf[64]; sprintf(buf, "%6.4f", x); return buf; }
|
2018-08-22 23:52:29 +00:00
|
|
|
string fts6(float x) { char buf[64]; sprintf(buf, "%8.6f", x); return buf; }
|
2017-12-27 18:10:34 +00:00
|
|
|
string ftsg(float x) { char buf[64]; sprintf(buf, "%4.2g", x); return buf; }
|
2017-07-16 21:00:55 +00:00
|
|
|
|
|
|
|
string ftssmart(ld x) {
|
|
|
|
if(x == int(x)) return its(int(x));
|
|
|
|
if(abs(x) > 1) return fts4(x);
|
2017-10-27 18:08:48 +00:00
|
|
|
char buf[64]; sprintf(buf, "%.10e", (float) x);
|
|
|
|
return buf;
|
2017-07-16 21:00:55 +00:00
|
|
|
}
|
|
|
|
|
2017-12-22 20:58:09 +00:00
|
|
|
/*
|
|
|
|
string fts_smartdisplay(ld x, int maxdisplay) {
|
|
|
|
string rv;
|
|
|
|
if(x > 1e9 || x < -1e9) retrun fts(x);
|
|
|
|
if(x<0) { rv = "-"; x = -x; }
|
|
|
|
int i = int(x);
|
|
|
|
rv += its(i);
|
|
|
|
x -= i;
|
|
|
|
bool nonzero = i;
|
|
|
|
if(x == 0) return rv;
|
|
|
|
if(x < 1e-9 && nonzero) return rv;
|
|
|
|
rv += ".";
|
|
|
|
while(maxdisplay > 0) {
|
|
|
|
x *= 10;
|
|
|
|
rv += '0' + int(x);
|
|
|
|
if(int(x)) nonzero = true;
|
|
|
|
x -= int(x);
|
|
|
|
if(x == 0) return rv;
|
|
|
|
if(x < 1e-9 && nonzero) return rv;
|
|
|
|
maxdisplay--;
|
|
|
|
}
|
|
|
|
} */
|
|
|
|
|
2017-03-23 10:53:57 +00:00
|
|
|
string cts(char c) { char buf[8]; buf[0] = c; buf[1] = 0; return buf; }
|
|
|
|
string llts(long long i) {
|
|
|
|
// sprintf does not work on Windows IIRC
|
|
|
|
if(i < 0) return "-" + llts(-i);
|
|
|
|
if(i < 10) return its((int) i);
|
|
|
|
return llts(i/10) + its(i%10);
|
|
|
|
}
|
|
|
|
string itsh(int i) {static char buf[16]; sprintf(buf, "%03X", i); return buf; }
|
2017-08-06 12:50:16 +00:00
|
|
|
string itsh2(int i) {static char buf[16]; sprintf(buf, "%02X", i); return buf; }
|
|
|
|
string itsh8(int i) {static char buf[16]; sprintf(buf, "%08X", i); return buf; }
|
2017-03-23 10:53:57 +00:00
|
|
|
|
2017-12-14 01:52:00 +00:00
|
|
|
int gcd(int i, int j) {
|
|
|
|
return i ? gcd(j%i, i) : j;
|
|
|
|
}
|
|
|
|
|
2017-12-28 15:46:10 +00:00
|
|
|
int gmod(int i, int j) {
|
|
|
|
i %= j; if(i<0) i += j;
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
2017-12-28 17:39:49 +00:00
|
|
|
ld frac(ld x) {
|
|
|
|
x -= int(x);
|
|
|
|
if(x < 0) x++;
|
|
|
|
return x;
|
|
|
|
}
|
|
|
|
|
2017-03-23 10:53:57 +00:00
|
|
|
// debug utilities
|
|
|
|
|
2017-07-22 23:33:27 +00:00
|
|
|
#if CAP_PROFILING
|
2017-03-23 10:53:57 +00:00
|
|
|
|
|
|
|
#define FRAMES 64
|
|
|
|
#define CATS 16
|
|
|
|
|
|
|
|
long long proftable[16][FRAMES];
|
|
|
|
int pframeid;
|
|
|
|
|
|
|
|
void profile_frame() {
|
|
|
|
pframeid++; pframeid %= FRAMES;
|
|
|
|
for(int t=0; t<16; t++) proftable[t][pframeid] = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void profile_start(int t) { proftable[t][pframeid] -= getms(); }
|
|
|
|
void profile_stop(int t) { proftable[t][pframeid] += getms(); }
|
|
|
|
|
|
|
|
void profile_info() {
|
|
|
|
for(int t=0; t<16; t++) {
|
|
|
|
sort(proftable[t], proftable[t]+FRAMES);
|
|
|
|
if(proftable[t][FRAMES-1] == 0) continue;
|
|
|
|
long long sum = 0;
|
|
|
|
for(int f=0; f<FRAMES; f++) sum += proftable[t][f];
|
|
|
|
printf("Category %d: avg = %Ld, %Ld..%Ld..%Ld..%Ld..%Ld\n",
|
|
|
|
t, sum / FRAMES, proftable[t][0], proftable[t][16], proftable[t][32],
|
|
|
|
proftable[t][48], proftable[t][63]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
#define profile_frame()
|
|
|
|
#define profile_start(t)
|
|
|
|
#define profile_stop(t)
|
|
|
|
#define profile_info()
|
|
|
|
#endif
|
|
|
|
|
2017-12-28 15:46:10 +00:00
|
|
|
int whateveri, whateveri2;
|
|
|
|
|
|
|
|
purehookset hooks_tests;
|
2018-07-19 22:04:23 +00:00
|
|
|
|
|
|
|
bool appears(const string& haystack, const string& needle) {
|
|
|
|
return haystack.find(needle) != string::npos;
|
|
|
|
}
|
|
|
|
|
2018-08-18 22:25:43 +00:00
|
|
|
/* indenter */
|
|
|
|
|
|
|
|
int current_indentation;
|
|
|
|
|
|
|
|
struct indenter {
|
|
|
|
indenter() { current_indentation += 2; }
|
|
|
|
~indenter() { current_indentation -= 2; }
|
|
|
|
};
|
|
|
|
|
|
|
|
void doindent() { for(int i=0; i<current_indentation; i++) printf(" "); }
|
|
|
|
|
2018-09-10 17:28:12 +00:00
|
|
|
struct exp_parser {
|
|
|
|
string s;
|
|
|
|
int at;
|
|
|
|
exp_parser() { at = 0; }
|
|
|
|
|
|
|
|
bool ok() { return at == isize(s); }
|
|
|
|
char next() { if(at == isize(s) || at == -1) return 0; else return s[at]; }
|
|
|
|
|
|
|
|
bool eat(const char *c) {
|
|
|
|
int orig_at = at;
|
|
|
|
while(*c && *c == next()) at++, c++;
|
|
|
|
if(*c == 0) return true;
|
|
|
|
else at = orig_at;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
ld parse(int prio = 0) {
|
|
|
|
ld res;
|
|
|
|
if(eat("sin(")) res = sin(parsepar());
|
|
|
|
else if(eat("cos(")) res = cos(parsepar());
|
|
|
|
else if(eat("sinh(")) res = sinh(parsepar());
|
|
|
|
else if(eat("cosh(")) res = cosh(parsepar());
|
|
|
|
else if(eat("asin(")) res = asin(parsepar());
|
|
|
|
else if(eat("acos(")) res = acos(parsepar());
|
|
|
|
else if(eat("asinh(")) res = asinh(parsepar());
|
|
|
|
else if(eat("acosh(")) res = acosh(parsepar());
|
|
|
|
else if(eat("exp(")) res = exp(parsepar());
|
|
|
|
else if(eat("log(")) res = log(parsepar());
|
|
|
|
else if(next() == '(') at++, res = parsepar();
|
|
|
|
else {
|
|
|
|
string number;
|
|
|
|
while(true) {
|
|
|
|
char c = next();
|
|
|
|
if((c >= '0' && c <= '9') || among(c, 'e', 'p', '.'))
|
|
|
|
number += c, at++;
|
|
|
|
else break;
|
|
|
|
}
|
|
|
|
if(number == "e") res = exp(1);
|
|
|
|
else if(number == "p" || number == "pi") res = M_PI;
|
|
|
|
else if(number == "") at = -1;
|
|
|
|
else if(number[0] >= 'a' && number[0] <= 'z') at = -1;
|
|
|
|
else { std::stringstream ss; res = 0; ss << number; ss >> res; }
|
|
|
|
}
|
|
|
|
while(true) {
|
|
|
|
if(next() == '+' && prio == 0) at++, res = res + parse(1);
|
|
|
|
else if(next() == '-' && prio == 0) at++, res = res - parse(1);
|
|
|
|
else if(next() == '*' && prio <= 1) at++, res = res * parse(2);
|
|
|
|
else if(next() == '/' && prio <= 1) at++, res = res / parse(2);
|
|
|
|
else if(next() == '^') at++, res = pow(res, parse(3));
|
|
|
|
else break;
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
ld parsepar() {
|
|
|
|
ld res = parse();
|
|
|
|
if(next() != ')') { at = -1; return res; }
|
|
|
|
at++;
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
ld parseld(const string& s) {
|
|
|
|
exp_parser ep;
|
|
|
|
ep.s = s;
|
|
|
|
return ep.parse();
|
|
|
|
}
|
|
|
|
|
2018-06-10 23:58:31 +00:00
|
|
|
}
|