mirror of
https://github.com/zenorogue/hyperrogue.git
synced 2025-07-22 02:42:49 +00:00
moved bignum to util.cpp
This commit is contained in:
parent
7568accff7
commit
454024a42c
158
expansion.cpp
158
expansion.cpp
@ -15,164 +15,6 @@ int subtype(cell *c) {
|
|||||||
return patterns::getpatterninfo(c, patterns::PAT_NONE, 0).id;
|
return patterns::getpatterninfo(c, patterns::PAT_NONE, 0).id;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if HDR
|
|
||||||
struct bignum {
|
|
||||||
static const int BASE = 1000000000;
|
|
||||||
static const long long BASE2 = BASE * (long long)BASE;
|
|
||||||
vector<int> digits;
|
|
||||||
bignum() {}
|
|
||||||
bignum(int i) : digits() { digits.push_back(i); }
|
|
||||||
void be(int i) { digits.resize(1); digits[0] = i; }
|
|
||||||
bignum& operator +=(const bignum& b);
|
|
||||||
void addmul(const bignum& b, int factor);
|
|
||||||
string get_str(int max_length);
|
|
||||||
|
|
||||||
bool operator < (const bignum&) const;
|
|
||||||
|
|
||||||
ld leading() const {
|
|
||||||
switch(isize(digits)) {
|
|
||||||
case 0:
|
|
||||||
return 0;
|
|
||||||
case 1:
|
|
||||||
return digits.back();
|
|
||||||
default:
|
|
||||||
return digits.back() + ld(digits[isize(digits)-2]) / BASE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ld approx() const {
|
|
||||||
return leading() * pow(BASE, isize(digits) - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
ld log_approx() const {
|
|
||||||
return log(leading()) * log(BASE) * (isize(digits) - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
ld operator / (const bignum& b) const {
|
|
||||||
return leading() / b.leading() * pow(BASE, isize(digits) - isize(b.digits));
|
|
||||||
}
|
|
||||||
|
|
||||||
int approx_int() const {
|
|
||||||
if(isize(digits) > 1) return BASE;
|
|
||||||
if(digits.empty()) return 0;
|
|
||||||
return digits[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
long long approx_ll() const {
|
|
||||||
if(isize(digits) > 2) return BASE2;
|
|
||||||
if(digits.empty()) return 0;
|
|
||||||
if(isize(digits) == 1) return digits[0];
|
|
||||||
return digits[0] + digits[1] * (long long) BASE;
|
|
||||||
}
|
|
||||||
|
|
||||||
friend inline bignum operator +(bignum a, const bignum& b) { a.addmul(b, 1); return a; }
|
|
||||||
friend inline bignum operator -(bignum a, const bignum& b) { a.addmul(b, -1); return a; }
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bignum& bignum::operator +=(const bignum& b) {
|
|
||||||
int K = isize(b.digits);
|
|
||||||
if(K > isize(digits)) digits.resize(K);
|
|
||||||
int carry = 0;
|
|
||||||
for(int i=0; i<K || carry; i++) {
|
|
||||||
if(i >= isize(digits)) digits.push_back(0);
|
|
||||||
digits[i] += carry;
|
|
||||||
if(i < K) digits[i] += b.digits[i];
|
|
||||||
if(digits[i] >= BASE) {
|
|
||||||
digits[i] -= BASE;
|
|
||||||
carry = 1;
|
|
||||||
}
|
|
||||||
else carry = 0;
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool bignum::operator < (const bignum& b) const {
|
|
||||||
if(isize(digits) != isize(b.digits))
|
|
||||||
return isize(digits) < isize(b.digits);
|
|
||||||
for(int i = isize(digits)-1; i>=0; i--)
|
|
||||||
if(digits[i] != b.digits[i])
|
|
||||||
return digits[i] < b.digits[i];
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void bignum::addmul(const bignum& b, int factor) {
|
|
||||||
int K = isize(b.digits);
|
|
||||||
if(K > isize(digits)) digits.resize(K);
|
|
||||||
int carry = 0;
|
|
||||||
for(int i=0; i<K || (carry > 0 || carry < -1) || (carry == -1 && i < isize(digits)); i++) {
|
|
||||||
if(i >= isize(digits)) digits.push_back(0);
|
|
||||||
long long l = digits[i];
|
|
||||||
l += carry;
|
|
||||||
if(i < K) l += b.digits[i] * factor;
|
|
||||||
carry = 0;
|
|
||||||
if(l >= BASE) carry = l / BASE;
|
|
||||||
if(l < 0) carry = -(BASE-1-l) / BASE;
|
|
||||||
l -= carry * BASE;
|
|
||||||
digits[i] = l;
|
|
||||||
}
|
|
||||||
if(carry < 0) digits.back() -= BASE;
|
|
||||||
while(isize(digits) && digits.back() == 0) digits.pop_back();
|
|
||||||
}
|
|
||||||
|
|
||||||
EX bignum hrand(bignum b) {
|
|
||||||
bignum res;
|
|
||||||
int d = isize(b.digits);
|
|
||||||
while(true) {
|
|
||||||
res.digits.resize(d);
|
|
||||||
for(int i=0; i<d-1; i++) res.digits[i] = hrand(bignum::BASE);
|
|
||||||
res.digits.back() = hrand(b.digits.back() + 1);
|
|
||||||
if(res < b) return res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
EX void operator ++(bignum &b, int) {
|
|
||||||
int i = 0;
|
|
||||||
while(true) {
|
|
||||||
if(isize(b.digits) == i) { b.digits.push_back(1); break; }
|
|
||||||
else if(b.digits[i] == bignum::BASE-1) {
|
|
||||||
b.digits[i] = 0;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
b.digits[i]++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
EX void operator --(bignum &b, int) {
|
|
||||||
int i = 0;
|
|
||||||
while(true) {
|
|
||||||
if(isize(b.digits) == i) { b.digits.push_back(bignum::BASE-1); break; }
|
|
||||||
else if(b.digits[i] == 0) {
|
|
||||||
b.digits[i] = bignum::BASE-1;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
b.digits[i]--;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
string bignum::get_str(int max_length) {
|
|
||||||
if(digits.empty()) return "0";
|
|
||||||
string ret = its(digits.back());
|
|
||||||
for(int i=isize(digits)-2; i>=0; i--) {
|
|
||||||
if(isize(ret) > max_length && i) {
|
|
||||||
ret += XLAT(" (%1 more digits)", its(9 * (i+1)));
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret += " ";
|
|
||||||
string val = its(digits[i]);
|
|
||||||
while(isize(val) < 9) val = "0" + val;
|
|
||||||
ret += val;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void canonicize(vector<int>& t) {
|
void canonicize(vector<int>& t) {
|
||||||
for(int i=2; i<isize(t); i++)
|
for(int i=2; i<isize(t); i++)
|
||||||
if((t[i] & 3) == 1 && (t[i-1] & 3) != 1)
|
if((t[i] & 3) == 1 && (t[i-1] & 3) != 1)
|
||||||
|
183
util.cpp
183
util.cpp
@ -289,4 +289,187 @@ EX string parser_help() {
|
|||||||
"(a)sin(h), (a)cos(h), (a)tan(h), exp, log, abs, re, im, conj, let(t=...,...t...), floor, frac, e, i, pi, s, ms, mousex, mousey, mousez, shot [1 if taking screenshot/animation], to01, random, ifp(a,v,w) [if positive]");
|
"(a)sin(h), (a)cos(h), (a)tan(h), exp, log, abs, re, im, conj, let(t=...,...t...), floor, frac, e, i, pi, s, ms, mousex, mousey, mousez, shot [1 if taking screenshot/animation], to01, random, ifp(a,v,w) [if positive]");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if HDR
|
||||||
|
struct bignum {
|
||||||
|
static const int BASE = 1000000000;
|
||||||
|
static const long long BASE2 = BASE * (long long)BASE;
|
||||||
|
vector<int> digits;
|
||||||
|
bignum() {}
|
||||||
|
bignum(int i) : digits() { digits.push_back(i); }
|
||||||
|
void be(int i) { digits.resize(1); digits[0] = i; }
|
||||||
|
bignum& operator +=(const bignum& b);
|
||||||
|
void addmul(const bignum& b, int factor);
|
||||||
|
string get_str(int max_length) const;
|
||||||
|
|
||||||
|
bool operator < (const bignum&) const;
|
||||||
|
|
||||||
|
ld leading() const {
|
||||||
|
switch(isize(digits)) {
|
||||||
|
case 0:
|
||||||
|
return 0;
|
||||||
|
case 1:
|
||||||
|
return digits.back();
|
||||||
|
default:
|
||||||
|
return digits.back() + ld(digits[isize(digits)-2]) / BASE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ld approx() const {
|
||||||
|
return leading() * pow(BASE, isize(digits) - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
ld log_approx() const {
|
||||||
|
return log(leading()) * log(BASE) * (isize(digits) - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
ld approx_div(const bignum& b) const {
|
||||||
|
return leading() / b.leading() * pow(BASE, isize(digits) - isize(b.digits));
|
||||||
|
}
|
||||||
|
|
||||||
|
int approx_int() const {
|
||||||
|
if(isize(digits) > 1) return BASE;
|
||||||
|
if(digits.empty()) return 0;
|
||||||
|
return digits[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool nonzero() { return approx_ld() != 0; }
|
||||||
|
|
||||||
|
bignum randomized_div(int x) const;
|
||||||
|
|
||||||
|
ld approx_ld() const {
|
||||||
|
ld res = 0;
|
||||||
|
for(int i=0; i<isize(digits); i++) res += digits[i] * pow(BASE, i);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
long long approx_ll() const {
|
||||||
|
if(isize(digits) > 2) return BASE2;
|
||||||
|
if(digits.empty()) return 0;
|
||||||
|
if(isize(digits) == 1) return digits[0];
|
||||||
|
return digits[0] + digits[1] * (long long) BASE;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend inline bignum operator +(bignum a, const bignum& b) { a.addmul(b, 1); return a; }
|
||||||
|
friend inline bignum operator -(bignum a, const bignum& b) { a.addmul(b, -1); return a; }
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bignum& bignum::operator +=(const bignum& b) {
|
||||||
|
int K = isize(b.digits);
|
||||||
|
if(K > isize(digits)) digits.resize(K);
|
||||||
|
int carry = 0;
|
||||||
|
for(int i=0; i<K || carry; i++) {
|
||||||
|
if(i >= isize(digits)) digits.push_back(0);
|
||||||
|
digits[i] += carry;
|
||||||
|
if(i < K) digits[i] += b.digits[i];
|
||||||
|
if(digits[i] >= BASE) {
|
||||||
|
digits[i] -= BASE;
|
||||||
|
carry = 1;
|
||||||
|
}
|
||||||
|
else carry = 0;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool bignum::operator < (const bignum& b) const {
|
||||||
|
if(isize(digits) != isize(b.digits))
|
||||||
|
return isize(digits) < isize(b.digits);
|
||||||
|
for(int i = isize(digits)-1; i>=0; i--)
|
||||||
|
if(digits[i] != b.digits[i])
|
||||||
|
return digits[i] < b.digits[i];
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bignum bignum::randomized_div(int x) const {
|
||||||
|
bignum res = self;
|
||||||
|
long long carry = 0;
|
||||||
|
int K = isize(res.digits);
|
||||||
|
for(int i=K-1; i>=0; i--) {
|
||||||
|
carry *= BASE;
|
||||||
|
carry += digits[i];
|
||||||
|
tie(carry, res.digits[i]) = make_pair(carry % x, carry / x);
|
||||||
|
}
|
||||||
|
while(isize(res.digits) && res.digits.back() == 0) res.digits.pop_back();
|
||||||
|
if(rand() % x < carry) res += 1;
|
||||||
|
println(hlog, get_str(100), " / ", x, " = ", res.get_str(100));
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bignum::addmul(const bignum& b, int factor) {
|
||||||
|
int K = isize(b.digits);
|
||||||
|
if(K > isize(digits)) digits.resize(K);
|
||||||
|
int carry = 0;
|
||||||
|
for(int i=0; i<K || (carry > 0 || carry < -1) || (carry == -1 && i < isize(digits)); i++) {
|
||||||
|
if(i >= isize(digits)) digits.push_back(0);
|
||||||
|
long long l = digits[i];
|
||||||
|
l += carry;
|
||||||
|
if(i < K) l += b.digits[i] * factor;
|
||||||
|
carry = 0;
|
||||||
|
if(l >= BASE) carry = l / BASE;
|
||||||
|
if(l < 0) carry = -(BASE-1-l) / BASE;
|
||||||
|
l -= carry * BASE;
|
||||||
|
digits[i] = l;
|
||||||
|
}
|
||||||
|
if(carry < 0) digits.back() -= BASE;
|
||||||
|
while(isize(digits) && digits.back() == 0) digits.pop_back();
|
||||||
|
}
|
||||||
|
|
||||||
|
EX bignum hrand(bignum b) {
|
||||||
|
bignum res;
|
||||||
|
int d = isize(b.digits);
|
||||||
|
while(true) {
|
||||||
|
res.digits.resize(d);
|
||||||
|
for(int i=0; i<d-1; i++) res.digits[i] = hrand(bignum::BASE);
|
||||||
|
res.digits.back() = hrand(b.digits.back() + 1);
|
||||||
|
if(res < b) return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EX void operator ++(bignum &b, int) {
|
||||||
|
int i = 0;
|
||||||
|
while(true) {
|
||||||
|
if(isize(b.digits) == i) { b.digits.push_back(1); break; }
|
||||||
|
else if(b.digits[i] == bignum::BASE-1) {
|
||||||
|
b.digits[i] = 0;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
b.digits[i]++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EX void operator --(bignum &b, int) {
|
||||||
|
int i = 0;
|
||||||
|
while(true) {
|
||||||
|
if(isize(b.digits) == i) { b.digits.push_back(bignum::BASE-1); break; }
|
||||||
|
else if(b.digits[i] == 0) {
|
||||||
|
b.digits[i] = bignum::BASE-1;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
b.digits[i]--;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string bignum::get_str(int max_length) const {
|
||||||
|
if(digits.empty()) return "0";
|
||||||
|
string ret = its(digits.back());
|
||||||
|
for(int i=isize(digits)-2; i>=0; i--) {
|
||||||
|
if(isize(ret) > max_length && i) {
|
||||||
|
ret += XLAT(" (%1 more digits)", its(9 * (i+1)));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret += " ";
|
||||||
|
string val = its(digits[i]);
|
||||||
|
while(isize(val) < 9) val = "0" + val;
|
||||||
|
ret += val;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user