mirror of
				https://github.com/zenorogue/hyperrogue.git
				synced 2025-10-30 21:42:59 +00:00 
			
		
		
		
	moved bignum to util.cpp
This commit is contained in:
		
							
								
								
									
										158
									
								
								expansion.cpp
									
									
									
									
									
								
							
							
						
						
									
										158
									
								
								expansion.cpp
									
									
									
									
									
								
							| @@ -15,164 +15,6 @@ int subtype(cell *c) { | ||||
|   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) { | ||||
|   for(int i=2; i<isize(t); i++) | ||||
|     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]"); | ||||
|   } | ||||
|  | ||||
| #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; | ||||
|   } | ||||
|  | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Zeno Rogue
					Zeno Rogue