11#pragma  once
2+ #include  < cassert> 
23#include  < cstdint> 
34#include  < iostream> 
45#include  < string> 
56#include  < vector> 
67
7- std::string uint64_t_to_string (uint64_t  val);
8- uint64_t  string_to_uint64_t (const  std::string &val);
9- void  mul_2_64_add_other (std::string &val, uint64_t  other);
10- void  div_mod_2_64 (const  std::string &val, std::string *rem);
11- 
12- #define  __BIGINT_OPERATOR_DECL (op, alter )    \
13-   big_int alter (const  big_int &other) const ; \
14-   big_int operator  op (const  big_int &other) const  { return  alter (other); }
15- #define  __BIGINT_OPERATOR_LOGIC_DECL (op, alter ) \
16-   bool  alter (const  big_int &other) const ;       \
17-   bool  operator  op (const  big_int &other) const  { return  alter (other); }
18- 
19- #define  __BIGINT_OPERATOR_SHIFT_DECL (type )                           \
20-   big_int shift_left (type other) const ;                              \
21-   big_int operator <<(type other) const  { return  shift_left (other); } \
22-   big_int shift_right (type other) const ;                             \
23-   big_int operator >>(type other) const  { return  shift_right (other); }
24- 
258//  most 64bit on the highest index
269class  big_int  {
2710 private: 
2811  std::vector<uint64_t > values;
29-   std::string values_str;
12+   //  mutable = non logic state
13+   mutable  std::string values_str;
3014  bool  negative = false ;
3115  const  static  uint16_t  max_thread;
3216
3317  //  For positive only
3418  big_int (std::vector<uint64_t > values) : values(values) {}
19+   std::string uint64_to_string (uint64_t  val) {
20+     std::string res;
21+     if  (!val) return  " 0" 
22+     while  (val) {
23+       res.insert (res.begin (), val % 10  + ' 0' 
24+       val /= 10 ;
25+     }
26+     return  res;
27+   }
28+ 
29+   uint64_t  string_to_uint64_t (const  std::string &val) {
30+     uint64_t  res = 0 ;
31+     for  (auto  c : val) res = res * 10  + c - ' 0' 
32+     return  res;
33+   }
34+ 
35+   void  mul_2_64_add_other (std::string &val, uint64_t  other) {
36+     using  namespace  std ; 
37+     if  (val.empty () || val == " 0" 
38+       val = uint64_to_string (other);
39+       return ;
40+     }
41+     std::string res;
42+     //  multiply
43+     std::vector<int > tmpres (val.size () + big_int::two_pow_64.size (), 0 );
44+     for  (size_t  i = 0 ; i < val.size (); ++i) {
45+       size_t  rev_i = val.size () - 1  - i;
46+       for  (size_t  j = 0 ; j < big_int::two_pow_64.size (); ++j) {
47+         size_t  rev_j = big_int::two_pow_64.size () - 1  - j;
48+         int  mul = (val[rev_i] - ' 0' ' 0' 
49+         size_t  p1 = rev_i + rev_j, p2 = p1 + 1 ;
50+         int  sum = tmpres[p2] + mul;
51+         tmpres[p2] = sum % 10 ;
52+         tmpres[p1] += sum / 10 ;
53+       }
54+     }
55+ 
56+     if  (!other) return ;
57+ 
58+     //  add the other
59+     std::string b = uint64_to_string (other);
60+     int  carry = 0 ;
61+ 
62+     for  (size_t  i = 0 ; i < b.size (); ++i) {
63+       size_t  rev_i = tmpres.size () - 1  - i;
64+       size_t  rev_i_b = b.size () - 1  - i;
65+       int  sum = b[rev_i_b] - ' 0' 
66+       sum += carry;
67+       carry = sum / 10 ;
68+       tmpres[rev_i] = sum % 10 ;
69+     }
70+ 
71+     for  (int  i = 0 ; carry && i < tmpres.size (); ++i) {
72+       int  sum = tmpres[tmpres.size () - i - 1 ] + carry;
73+       tmpres[tmpres.size () - i - 1 ] = sum % 10 ;
74+       carry = sum / 10 ;
75+     }
76+ 
77+     if  (carry) tmpres.insert (tmpres.begin (), 1 , carry);
78+ 
79+     while  (!tmpres[0 ]) tmpres.erase (tmpres.begin ());
80+     res.resize (tmpres.size ());
81+     for  (size_t  i = 0 ; i < tmpres.size (); ++i) res[i] = tmpres[i] + ' 0' 
82+ 
83+     val = res;
84+   }
85+ 
86+   //  TODO : Implement this method
87+   void  div_mod_2_64 (std::string &val, std::string *remainder) const  {
88+     if  (val.size () < big_int::two_pow_64.size ()) {
89+       if  (remainder) *remainder = val;
90+       val = " " 
91+       return ;
92+     }
93+     std::vector<int > sub_res (val.size (), 0 );
94+     size_t  offset = val.size () - big_int::two_pow_64.size ();
95+     uint64_t  div_res = 0 ;
96+     bool  greater_equal = true ;
97+     bool  carry = 0 ;
98+     while  (greater_equal) {
99+       for  (size_t  i = 0 ; i < val.size (); ++i) {
100+         size_t  rev_val_i = val.size () - 1  - i;
101+         size_t  rev_2_64_i = rev_val_i - offset;
102+       }
103+     }
104+   }
35105
36106 public: 
37107  //  done
@@ -40,51 +110,180 @@ class big_int {
40110      : values(values), negative(negative) {}
41111
42112  big_int (uint64_t  value) {
43-     if  (value < (1ULL  << 63 ))
44-       values = {value};
113+     if  (value < (1ULL  << 63 )) values = {value};
45114    else  {
46115      values = {~value + 1 };
47116      this ->negative  = true ;
48117    }
49118  }
50119
51-   big_int (const  std::string &value);
120+   big_int (std::string value) {
121+     std::string rem = " 0" 
122+     std::vector<uint64_t > chunks;
123+     while  (!value.empty ()) {
124+       div_mod_2_64 (value, &rem);
125+       chunks.push_back (string_to_uint64_t (rem));
126+     }
127+   }
128+ 
129+   std::string to_string () const  {}
130+ 
131+ #define  FUNC_OP (op ) big_int op (const  big_int &other) const 
52132
53-   //  c/cpp aneh banget, perlu const di belakang untuk menandakan fungsi tidak 
54-   //  merubah big_int 
55-   std::string  to_string ()  const ;
133+   FUNC_OP(add) { 
134+     std::vector< uint64_t > this_copy =  this -> values , other_copy = other. values , 
135+                           result ;
56136
57-   static  const  big_int ONE;
137+     //  for flag and result
138+     bool  negative = false ;
58139
59-   __BIGINT_OPERATOR_DECL (+, add);
60-   __BIGINT_OPERATOR_DECL (-, min);
61-   __BIGINT_OPERATOR_DECL (*, mul);
62-   __BIGINT_OPERATOR_DECL (/, div);
140+     //  padding
141+     if  (this ->values .size () != other.values .size ()) {
142+       size_t  pad = this ->values .size () > other.values .size ()
143+                        ? this ->values .size () - other.values .size ()
144+                        : other.values .size () - this ->values .size ();
145+       this ->values .size () > other.values .size ()
146+           ? other_copy.insert (other_copy.begin (), pad, 0 )
147+           : this_copy.insert (this_copy.begin (), pad, 0 );
148+     }
63149
150+     //  inverse bit and add 1 for negative
151+     if  (this ->negative  != other.negative ) {
152+       negative = true ;
153+       bool  carry = 1 ;
154+       if  (this ->negative ) {
155+         for  (size_t  i = 0 ; i < this_copy.size (); ++i) {
156+           this_copy[i] = ~this_copy[i] + carry;
157+           carry = this_copy[i] == 0 ;
158+         }
159+       } else  {
160+         for  (size_t  i = 0 ; i < this_copy.size (); ++i) {
161+           other_copy[i] = ~other_copy[i] + carry;
162+           carry = other_copy[i] == 0 ;
163+         }
164+       }
165+     }
166+ 
167+     bool  carry = false ;
168+     for  (size_t  i = 0 ; i < this_copy.size (); ++i) {
169+       result.push_back (this_copy[i] + other_copy[i] + carry);
170+       carry =
171+           (result[i] < this_copy[i] || (carry && result[i] == this_copy[i]));
172+     }
173+ 
174+     //  if carry (outside to make sure if false skip) but both not equal
175+     //  negative=false, if not add the carry
176+     if  (carry) {
177+       if  (negative) negative = false ;
178+       else  {
179+         result.push_back (1 );
180+         if  (this ->negative ) negative = true ;
181+       }
182+     }
183+ 
184+     return  big_int (result, negative);
185+   }
186+ 
187+   FUNC_OP (min) {
188+     big_int big_new (other.values , !other.negative );
189+     return  this ->add (big_new);
190+   }
191+   FUNC_OP (mul) {
192+     size_t  res_bit = (this ->values .size () << 6 ) + (other.values .size () << 6 );
193+     if  (res_bit < this ->values .size ())
194+       throw  std::runtime_error (" overflow reached" 
195+ 
196+     big_int res (0 );
197+ 
198+     if  (this ->negative  ^ other.negative ) res.negative  = true ;
199+ 
200+     for  (size_t  i = 0 ; i < other.values .size (); ++i) {
201+       uint64_t  factor = other.values [i];
202+       for  (uint8_t  j = 1 ; j < uint8_t (1  << 6 ); ++j) {
203+         if  (factor & (1ULL  << j)) res = res + (*this  << j);
204+         factor = factor >> 1 ;
205+       }
206+     }
207+     return  res;
208+   }
209+ 
210+   FUNC_OP (div) {}
211+ #undef  FUNC_OP
212+ 
213+ #define  OPERATOR_DECL (op, alter ) \
214+   big_int operator  op (const  big_int &other) const  { return  alter (other); }
215+   OPERATOR_DECL (+, add);
216+   OPERATOR_DECL (-, min);
217+   OPERATOR_DECL (*, mul);
218+   OPERATOR_DECL (/, div);
219+ #undef  OPERATOR_DECL
64220  //  special case
65-   big_int operator ++(int ) { return  add (ONE); }
66-   big_int operator --(int ) { return  min (ONE); }
67-   bool  operator !() { return  values_str.empty () || values_str == " 0" 
68- 
69-   __BIGINT_OPERATOR_DECL (&, _and)
70-   __BIGINT_OPERATOR_DECL (|, _or)
71-   __BIGINT_OPERATOR_DECL (^, _xor)
72- 
73-   __BIGINT_OPERATOR_LOGIC_DECL (>, gt);
74-   __BIGINT_OPERATOR_LOGIC_DECL (>=, gteq);
75-   __BIGINT_OPERATOR_LOGIC_DECL (<, lt);
76-   __BIGINT_OPERATOR_LOGIC_DECL (<=, lteq);
77-   __BIGINT_OPERATOR_LOGIC_DECL (==, equal);
78-   __BIGINT_OPERATOR_LOGIC_DECL (!=, noteq);
79-   __BIGINT_OPERATOR_LOGIC_DECL (&&, andand);
80-   __BIGINT_OPERATOR_LOGIC_DECL (||, oror);
81- 
82-   //  uint64_t udah cukup, terlanjur bikin makronya males ngapus
83-   __BIGINT_OPERATOR_SHIFT_DECL (size_t );
84- #undef  __BIGINT_OPERATOR_DECL
85- #undef  __BIGINT_OPERATOR_LOGIC_DECL
86- #undef  __BIGINT_OPERATOR_SHIFT_DECL
87- };
221+   big_int operator ++(int ) { return  add (big_int (1 )); }
222+   big_int operator --(int ) { return  min (big_int (1 )); }
223+   bool  operator !() {
224+     return  (values.size () == 1  && values[0 ] == 0 ) || values.empty ();
225+   }
226+ 
227+ #define  BITWISE (op ) big_int operator  op (const  big_int &other) const 
228+ 
229+   BITWISE(&) {}
230+ #undef  BITWISE
231+ 
232+ #define  OPERATOR_LOGIC_DECL (op, alter )    \
233+   bool  alter (const  big_int &other) const ; \
234+   bool  operator  op (const  big_int &other) const  { return  alter (other); }
235+ 
236+   OPERATOR_LOGIC_DECL (>, gt);
237+   OPERATOR_LOGIC_DECL (>=, gteq);
238+   OPERATOR_LOGIC_DECL (<, lt);
239+   OPERATOR_LOGIC_DECL (<=, lteq);
240+   OPERATOR_LOGIC_DECL (==, equal);
241+   OPERATOR_LOGIC_DECL (!=, noteq);
242+   OPERATOR_LOGIC_DECL (&&, andand);
243+   OPERATOR_LOGIC_DECL (||, oror);
244+ 
245+   big_int shift_left (uint64_t  k) const  {
246+     std::vector<uint64_t > res_values (this ->values );
247+     if  (!k) return  big_int (res_values, this ->negative );
248+     assert ((k >> 6 ) + res_values.size () > res_values.size ());
249+     if  (k >> 6 ) res_values.insert (res_values.end (), k >> 6 , 0 );
250+     uint64_t  carry = 0 ;
251+     uint64_t  bits = (k & 63ULL );
252+     //  mencegah shifting 64 kali jika k kelipatan 64 karena 64-0 dilewatkan
253+     if  (bits) {
254+       for  (auto  it = res_values.rbegin (); it != res_values.rend (); ++it) {
255+         uint64_t  tmp = *it << bits | carry;
256+         carry = *it >> (64ULL  - bits);
257+         *it = tmp;
258+       }
259+     }
260+     return  big_int (res_values, this ->negative );
261+   }
262+ 
263+   big_int operator <<(uint64_t  k) const  { return  shift_left (k); }
264+ 
265+   big_int shift_right (uint64_t  k) const  {
266+     std::vector<uint64_t > res_values (this ->values );
267+     if  (!k) return  big_int (res_values, this ->negative );
268+     if  (k >> 6  >= res_values.size ()) return  big_int ({0 }, this ->negative );
269+     if  (k >> 6 ) res_values.resize (res_values.size () - (k >> 6 ));
270+     uint64_t  carry = 0 ;
271+     uint64_t  bits = (k & 63ULL );
272+     if  (bits) {
273+       for  (auto  it = res_values.begin (); it != res_values.end (); ++it) {
274+         uint64_t  tmp = *it >> bits | carry;
275+         carry = *it << (64ULL  - bits);
276+         *it = tmp;
277+       }
278+     }
279+     while  (res_values.size () > 1  && !res_values.back ()) res_values.pop_back ();
280+     return  big_int (res_values, this ->negative );
281+   }
282+ 
283+   big_int operator >>(uint64_t  k) const  { return  shift_right (k); }
284+ };  //  END big_int class
285+ //  static member init
286+ const  std::string two_pow_64 = " 18446744073709551616" 
88287
89288inline  big_int operator " " unsigned  long  long  i) { return  big_int (i); }
90289inline  big_int operator " " const  char  *str, size_t  size) {
0 commit comments