ht's Scheme Interpreter  1.0
a simplified scheme interpreter implementation
bigint.cpp
Go to the documentation of this file.
1 #include <iostream>
2 #include <cstdint>
3 #include <cstddef>
4 #include <vector>
5 #include <string>
6 #include <cmath>
7 #include <cctype>
8 #include <stdexcept>
9 #include <cassert>
10 #include <algorithm>
11 #include <utility>
12 #include <functional>
13 #include "bigint.hpp"
14 #include "utility/strutility.hpp"
15 bool BigInt::isZero() const
16 {
17  return len ==1 && d[0]==0;
18 }
19 
20 BigInt::BigInt(long long num)
21 {
22  assign(num);
23 }
24 
25 BigInt::BigInt(const std::string& s)
26 {
27  assign(s);
28 }
29 
31 {
32  assign(0);
33 }
34 
35 BigInt& BigInt::assign(long long num)
36 {
37  nonNeg = num>=0;
38  num = std::abs(num);
39  d.clear();
40  len=0;
41 
42  if (!num)
43  {
44  len=1;
45  d.push_back(0);
46  } else
47  while (num>0)
48  {
49  d.push_back(num % 10000);
50  ++len;
51  num /= 10000;
52  }
53  return *this;
54 };
55 
56 BigInt& BigInt::assign(const std::string& s)
57 {
58  d.clear();
59  len=0;
60  nonNeg = true;
61  int beg = -1;
62  for(size_t i=0;i<s.size();++i)
63  if (s[i]=='-')
64  nonNeg = !nonNeg;
65  else if (isdigit(s[i]))
66  {
67  beg = i;
68  break;
69  } else if (s[i]!='+')
70  throw std::runtime_error(s+" is not a valid BigInt");
71  if (beg == -1)
72  throw std::runtime_error(s+ " is not a valid BigInt");
73  while (beg < s.size() && s[beg]=='0')
74  ++beg;
75  if (beg >= s.size())
76  {
77  len =1;
78  d.push_back(0);
79  return *this;
80  }
81  int pos = s.size() -1;
82  while(pos >= beg)
83  {
84  int32_t cur=char2int(s[pos]);
85  if (pos-1 >=beg) cur += 10*char2int(s[pos-1]);
86  if (pos-2 >=beg) cur += 100*char2int(s[pos-2]);
87  if (pos-3 >=beg) cur += 1000*char2int(s[pos-3]);
88  d.push_back(cur);
89  ++len;
90  pos -= 4;
91  }
92  return *this;
93 }
94 
96 {
97  BigInt ans(*this);
98  if (!isZero())
99  ans.nonNeg = !ans.nonNeg;
100  return ans;
101 }
102 
103 template<typename CompareFunc>
104 bool rawCompare(const BigInt& a, const BigInt& b)
105 {
106  CompareFunc com = CompareFunc();
107  if (a.len != b.len ) return com(a.len, b.len);
108  for (int i=a.len-1; i>=0; --i)
109  if (a.d[i] != b.d[i])
110  return com(a.d[i],b.d[i]);
111  return false;
112 }
113 
114 bool BigInt::rawSmaller(const BigInt& b) const
115 {
116  return rawCompare< std::less<int32_t> >(*this, b);
117 }
118 
119 bool BigInt::rawGreater(const BigInt& b) const
120 {
121  return rawCompare< std::greater<int32_t> >(*this, b);
122 }
123 
124 bool BigInt::operator< (const BigInt& b) const
125 {
126  if (!nonNeg && b.nonNeg) return true;
127  if (!nonNeg && !b.nonNeg) return rawGreater(b);
128  if (nonNeg && !b.nonNeg) return false;
129  if (nonNeg && b.nonNeg) return rawSmaller(b);
130  return false;
131 }
132 
133 bool BigInt::operator > (const BigInt& b) const
134 {
135  return b<*this;
136 }
137 
138 bool BigInt::operator== (const BigInt& b) const
139 {
140  if (len!=b.len) return false;
141  for (int i=0; i<len; ++i)
142  if (d[i]!=b.d[i]) return false;
143  return true;
144 }
145 
146 bool BigInt::operator != (const BigInt& b) const
147 {
148  return !(*this == b);
149 }
150 
151 bool BigInt::operator >= (const BigInt& b) const
152 {
153  return *this >b || *this==b;
154 }
155 
156 bool BigInt::operator<= (const BigInt& b) const
157 {
158  return *this<b || *this==b;
159 }
160 
162 {
163  size_t oldsize = d.size();
164  len = std::max(len, b.len);
165  d.resize(len+1, 0); // cpp11 feature
166  int32_t jw=0;
167  for (size_t i=0; i<len; ++i)
168  {
169  d[i] += (i<b.len ? b.d[i] : 0) + jw;
170  jw = d[i] / 10000;
171  d[i] %= 10000;
172  }
173  if (jw>0)
174  {
175  ++len;
176  d[len-1] = jw;
177  }
178  return *this;
179 }
180 
181 
183 {
184  int32_t jw =0;
185  //std::cout<< "LOG: "<<*this<< " "<<b<<std::endl;
186  for (size_t i=0; i<len; ++i)
187  {
188  d[i] -= (i<b.len ? b.d[i] : 0) + jw;
189  jw=0;
190  while (d[i]<0)
191  {
192  ++jw;
193  d[i]+=10000;
194  }
195  }
196  assert (jw==0);
197  while (len>1 && d[len-1]==0) --len;
198  return *this;
199 }
200 
201 
202 BigInt& BigInt::operator += (const BigInt& b)
203 {
204  if (b.isZero()) return *this;
205  if (isZero()) { *this=b; return *this;}
206  if (! (nonNeg ^ b.nonNeg))
207  rawPlus(b);
208  else
209  if (nonNeg) // case +a -b
210  if (!rawSmaller(b)) //a>=b
211  rawMinus(b);
212  else //a<b
213  {
214  BigInt temp(b);
215  temp.rawMinus(*this);
216  temp.nonNeg = false;
217  *this = temp;
218  }
219  else //case -a +b
220  if (!rawSmaller(b)) //a>=b
221  {
222  rawMinus(b);
223  if (isZero()) nonNeg = true;
224  }
225  else //a<b
226  {
227  BigInt temp(b);
228  temp.rawMinus(*this);
229  temp.nonNeg = true;
230  *this = temp;
231  }
232  return *this;
233 }
234 
235 BigInt& BigInt::operator -= (const BigInt& b)
236 {
237  return this -> operator += (-b);
238 }
239 
240 std::istream& operator >>(std::istream& i, BigInt& b)
241 {
242  std::string s;
243  i>>s;
244  b.assign(s);
245  return i;
246 }
247 
248 std::ostream& operator <<(std::ostream& o , const BigInt& b)
249 {
250  if (!b.nonNeg) o<<'-';
251  for (int i=b.len-1; i>=0; --i)
252  {
253  if (i!=b.len-1)
254  {
255  if (b.d[i]<1000) o<<'0';
256  if (b.d[i]<100) o<<'0';
257  if (b.d[i]<10) o<<'0';
258  }
259  o<<b.d[i];
260  }
261  return o;
262 }
263 
264 BigInt BigInt::operator+ (const BigInt& b) const
265 {
266  BigInt ans(*this);
267  ans += b;
268  return ans;
269 }
270 
271 BigInt BigInt::operator- (const BigInt& b) const
272 {
273  BigInt ans(*this);
274  ans -= b;
275  return ans;
276 }
277 
278 BigInt BigInt::operator* (const BigInt& b) const
279 {
280  //std::cout<<" LOG: MULTI"<< *this<<" "<<b<<std::endl;
281  BigInt ans;
282  std::vector<int32_t> &v= ans.d;
283  v.resize(len+b.len+1, 0);
284  for (size_t i=0; i<len; ++i)
285  for (size_t j=0; j<b.len; ++j)
286  v[i+j] += d[i] * b.d[j];
287  int32_t jw = 0;
288  for (size_t i=0; i<len + b.len; ++i)
289  {
290  v[i] += jw;
291  jw = v[i] / 10000;
292  v[i] %= 10000;
293  }
294  assert(jw==0);
295  ans.len = len + b.len;
296  while (ans.len>1 && v[ans.len-1]==0) --ans.len;
297 
298  ans.nonNeg = !( nonNeg ^ b.nonNeg );
299  if (isZero() || b.isZero()) ans.nonNeg=true;
300  return ans;
301 }
302 
303 BigInt& BigInt::operator *= (const BigInt& b)
304 {
305  *this = (*this * b);
306  return *this;
307 }
308 
309 BigInt& BigInt::setSign(const bool sign)
310 {
311  nonNeg = sign;
312  return *this;
313 }
314 
315 std::pair<BigInt&, BigInt> BigInt::divandmod(const BigInt& b)
316 {
317  if (b.isZero()) throw std::runtime_error("division to zero");
318  nonNeg = !(nonNeg ^ b.nonNeg);
319  if (isZero()) nonNeg =true;
320  BigInt ten(10000), now;
321  //std::cout<<b<<std::endl;
322  for(int i=len-1; i>=0; --i)
323  {
324  now *= ten;
325  now += d[i];
326  d[i]=0;
327  int32_t l=0, r=10000;
328  int32_t mid = (l+r)/2;
329  while (l<r-1)
330  {
331  mid = (l+r)/2;
332  //std::cout<< l <<" "<<r<<" "<<(b*mid).setSign(true)<<" "<<now<<" "<<((b*mid).setSign(true)>now)<<std::endl;
333  if ((b*mid).setSign(true)>now)
334  r=mid-1;
335  else
336  l=mid;
337  }
338  mid =r;
339  //std::cout<<" after iter"<<l<<" "<<r<<std::endl;
340  while (mid>1 && (b*mid).setSign(true)>now) --mid;
341  d[i]=mid;
342  //std::cout<<" log in "<< __func__<< mid << " "<<now <<" "<<(b*mid).setSign(true) <<std::endl;
343  now-=(b*mid).setSign(true);
344  }
345  while (len>1 && d[len-1]==0) --len;
346 
347  std::pair<BigInt&, BigInt> ans(*this, now);
348  return ans;
349 }
350 
351 
352 
353 BigInt& BigInt::operator/= (const BigInt& b)
354 {
355  return divandmod(b).first;
356 }
357 
358 BigInt BigInt::operator / (const BigInt& b) const
359 {
360  BigInt ans(*this);
361  return ans/=b;
362 }
363 
364 BigInt& BigInt::operator %= (const BigInt& b)
365 {
366  *this = divandmod(b).second;
367  return *this;
368 }
369 
370 BigInt BigInt::operator % (const BigInt& b) const
371 {
372  BigInt ans(*this);
373  return ans %= b;
374 }
BigInt & operator/=(const BigInt &b)
Definition: bigint.cpp:353
std::pair< BigInt &, BigInt > divandmod(const BigInt &b)
Definition: bigint.cpp:315
BigInt & assign(long long num)
Definition: bigint.cpp:35
BigInt & operator%=(const BigInt &b)
Definition: bigint.cpp:364
BigInt(const std::string &s)
Definition: bigint.cpp:25
BigInt operator*(const BigInt &b) const
Definition: bigint.cpp:278
BigInt & operator-=(const BigInt &b)
Definition: bigint.cpp:235
bool operator>(const BigInt &b) const
Definition: bigint.cpp:133
int char2int(char c)
Definition: strutility.hpp:8
bool operator<=(const BigInt &b) const
Definition: bigint.cpp:156
bool rawGreater(const BigInt &b) const
Definition: bigint.cpp:119
BigInt & rawPlus(const BigInt &b)
Definition: bigint.cpp:161
bool operator<(const BigInt &b) const
Definition: bigint.cpp:124
BigInt()
Definition: bigint.cpp:30
BigInt(long long num)
Definition: bigint.cpp:20
size_t len
Definition: bigint.hpp:15
BigInt & operator+=(const BigInt &b)
Definition: bigint.cpp:202
bool operator>=(const BigInt &b) const
Definition: bigint.cpp:151
BigInt operator/(const BigInt &b) const
Definition: bigint.cpp:358
BigInt & operator*=(const BigInt &b)
Definition: bigint.cpp:303
BigInt & setSign(const bool sign)
Definition: bigint.cpp:309
BigInt & rawMinus(const BigInt &b)
Definition: bigint.cpp:182
BigInt operator-() const
Definition: bigint.cpp:95
bool isZero() const
Definition: bigint.cpp:15
bool operator!=(const BigInt &b) const
Definition: bigint.cpp:146
bool rawSmaller(const BigInt &b) const
Definition: bigint.cpp:114
BigInt operator%(const BigInt &b) const
Definition: bigint.cpp:370
std::vector< int32_t > d
Definition: bigint.hpp:14
std::istream & operator>>(std::istream &i, BigInt &b)
Definition: bigint.cpp:240
bool rawCompare(const BigInt &a, const BigInt &b)
Definition: bigint.cpp:104
BigInt operator+(const BigInt &b) const
Definition: bigint.cpp:264
bool operator==(const BigInt &b) const
Definition: bigint.cpp:138
BigInt operator-(const BigInt &b) const
Definition: bigint.cpp:271
bool nonNeg
Definition: bigint.hpp:16
BigInt & assign(const std::string &s)
Definition: bigint.cpp:56