LCOV - code coverage report
Current view: top level - tests - num.hpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 162 223 72.6 %
Date: 2024-02-03 18:59:18 Functions: 35 46 76.1 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // source:
       2             : // https://github.com/983/Num/blob/master/num.hpp
       3             : // License: 
       4             : // This is free and unencumbered software released into the public domain.
       5             : // 
       6             : // Anyone is free to copy, modify, publish, use, compile, sell, or
       7             : // distribute this software, either in source code form or as a compiled
       8             : // binary, for any purpose, commercial or non-commercial, and by any
       9             : // means.
      10             : // 
      11             : // In jurisdictions that recognize copyright laws, the author or authors
      12             : // of this software dedicate any and all copyright interest in the
      13             : // software to the public domain. We make this dedication for the benefit
      14             : // of the public at large and to the detriment of our heirs and
      15             : // successors. We intend this dedication to be an overt act of
      16             : // relinquishment in perpetuity of all present and future rights to this
      17             : // software under copyright law.
      18             : // 
      19             : // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
      20             : // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
      21             : // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
      22             : // IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
      23             : // OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
      24             : // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
      25             : // OTHER DEALINGS IN THE SOFTWARE.
      26             : // 
      27             : // For more information, please refer to <http://unlicense.org>
      28             : 
      29             : #pragma once
      30             : 
      31             : #include <math.h>
      32             : #include <stdint.h>
      33             : #include <limits.h>
      34             : 
      35             : #include <vector>
      36             : #include <algorithm>
      37             : 
      38             : 
      39             : //#pragma GCC diagnostic push
      40             : //#pragma GCC diagnostic ignored "-Weffc++"
      41             : //#pragma GCC diagnostic ignored "-Wpermissive"
      42             : 
      43             : 
      44             : class Num {
      45             : public:
      46             :     typedef uint64_t word;
      47             : 
      48             :     std::vector<word> words = {};
      49             :     bool neg = false;
      50             : 
      51       19200 :     static word word_mask(){
      52       19200 :         return (word)-1;
      53             :     }
      54             : 
      55       29976 :     static size_t word_bits(){
      56       29976 :         return sizeof(word)*CHAR_BIT;
      57             :     }
      58             : 
      59       19200 :     static word word_half_mask(){
      60       19200 :         return word_mask() >> word_bits()/2;
      61             :     }
      62             : 
      63             :     static word char_to_word(char c){
      64             :         switch (c){
      65             :             case '0': return 0;
      66             :             case '1': return 1;
      67             :             case '2': return 2;
      68             :             case '3': return 3;
      69             :             case '4': return 4;
      70             :             case '5': return 5;
      71             :             case '6': return 6;
      72             :             case '7': return 7;
      73             :             case '8': return 8;
      74             :             case '9': return 9;
      75             :             case 'a': case 'A': return 10;
      76             :             case 'b': case 'B': return 11;
      77             :             case 'c': case 'C': return 12;
      78             :             case 'd': case 'D': return 13;
      79             :             case 'e': case 'E': return 14;
      80             :             case 'f': case 'F': return 15;
      81             :             case 'g': case 'G': return 16;
      82             :             case 'h': case 'H': return 17;
      83             :             case 'i': case 'I': return 18;
      84             :             case 'j': case 'J': return 19;
      85             :             case 'k': case 'K': return 20;
      86             :             case 'l': case 'L': return 21;
      87             :             case 'm': case 'M': return 22;
      88             :             case 'n': case 'N': return 23;
      89             :             case 'o': case 'O': return 24;
      90             :             case 'p': case 'P': return 25;
      91             :             case 'q': case 'Q': return 26;
      92             :             case 'r': case 'R': return 27;
      93             :             case 's': case 'S': return 28;
      94             :             case 't': case 'T': return 29;
      95             :             case 'u': case 'U': return 30;
      96             :             case 'v': case 'V': return 31;
      97             :             case 'w': case 'W': return 32;
      98             :             case 'x': case 'X': return 33;
      99             :             case 'y': case 'Y': return 34;
     100             :             case 'z': case 'Z': return 35;
     101             :             default: return word_mask();
     102             :         }
     103             :     }
     104             : 
     105             :     static word word_gcd(word a, word b){
     106             :         while (1){
     107             :             if (a == 0) return b;
     108             :             b %= a;
     109             :             if (b == 0) return a;
     110             :             a %= b;
     111             :         }
     112             :     }
     113             : 
     114         400 :     Num(): neg(false){}
     115             : 
     116         200 :     Num(size_t n, word w, bool sign = false): words(n, w), neg(sign){}
     117             : 
     118         400 :     Num(const word *a, const word *b, bool sign = false) : words(a, b), neg(sign){}
     119             : 
     120         300 :     Num(const Num &a){
     121         300 :         words = a.words;
     122         300 :         neg = a.neg;
     123         300 :     }
     124             : 
     125         500 :     Num& operator = (const Num &a){
     126         500 :         words = a.words;
     127         500 :         neg = a.neg;
     128         500 :         return *this;
     129             :     }
     130             : 
     131         200 :     Num(int i): neg(i < 0){
     132         200 :         for (unsigned u = std::abs(i); u;){
     133           0 :             push_back(u);
     134             :             // carefully shift 'u' bit-by-bit because u >>= 32 might be undefined
     135           0 :             for (size_t j = 0; j < word_bits(); j++) u >>= 1;
     136             :         }
     137         200 :     }
     138             : 
     139             :     Num(const char *c, word base = 10, char **endptr = NULL): neg(false){
     140             :         // read sign
     141             :         if (*c == '-'){
     142             :             c++;
     143             :             neg = true;
     144             :         }
     145             :         // read digits
     146             :         for (;*c; c++){
     147             :             mul_word(base);
     148             :             word b = char_to_word(*c);
     149             :             if (b >= base) break;
     150             :             add_word(b);
     151             :         }
     152             :         if (endptr) *endptr = const_cast<char*>(c);
     153             :     }
     154             : 
     155         598 :     void resize(size_t n){
     156         598 :         words.resize(n);
     157         598 :     }
     158             : 
     159         180 :     void pop_back(){
     160         180 :         words.pop_back();
     161         180 :     }
     162             : 
     163           0 :     void push_back(word b){
     164           0 :         words.push_back(b);
     165           0 :     }
     166             : 
     167             :     word& back(){
     168             :         return words.back();
     169             :     }
     170             : 
     171             :     const word& back() const {
     172             :         return words.back();
     173             :     }
     174             : 
     175        6920 :     size_t size() const {
     176        6920 :         return words.size();
     177             :     }
     178             : 
     179       38382 :     word& operator [] (size_t i){
     180       38382 :         return words[i];
     181             :     }
     182             : 
     183       30212 :     const word& operator [] (size_t i) const {
     184       30212 :         return words[i];
     185             :     }
     186             : 
     187         400 :     Num& set_neg(bool sign){
     188         400 :         this->neg = sign;
     189         400 :         return *this;
     190             :     }
     191             : 
     192         770 :     Num& truncate(){
     193         950 :         while (size() > 0 && words.back() == 0) pop_back();
     194         770 :         return *this;
     195             :     }
     196             : 
     197         220 :     size_t bitlength() const {
     198         220 :         if (size() == 0) return 0;
     199         220 :         size_t last = size() - 1;
     200         220 :         while(last > 0 && (*this)[last] == 0) {
     201           0 :             --last;
     202             :         }
     203         220 :         size_t result = word_bitlength((*this)[last]) + last*word_bits();
     204         220 :         return result;
     205             :     }
     206             : 
     207             :     size_t count_trailing_zeros() const {
     208             :         for (size_t i = 0; i < size(); i++){
     209             :             word w = (*this)[i];
     210             :             if (w) return word_count_trailing_zeros(w) + i*word_bits();
     211             :         }
     212             :         return 0;
     213             :     }
     214             : 
     215         508 :     static int cmp_abs(const Num &a, const Num &b){
     216         508 :         size_t na = a.size(), nb = b.size();
     217         508 :         if (na != nb){
     218           0 :             return na < nb ? -1 : +1;
     219             :         }
     220         508 :         for (size_t i = na; i --> 0;){
     221         508 :             word wa = a[i], wb = b[i];
     222         508 :             if (wa != wb){
     223         508 :                 return wa < wb ? -1 : +1;
     224             :             }
     225             :         }
     226           0 :         return 0;
     227             :     }
     228             : 
     229             :     static int cmp(const Num &a, const Num &b){
     230             :         if (a.size() == 0 && b.size() == 0) return 0;
     231             :         if (!a.neg && !b.neg) return +cmp_abs(a, b);
     232             :         if ( a.neg &&  b.neg) return -cmp_abs(a, b);
     233             :         return a.neg && !b.neg ? -1 : +1;
     234             :     }
     235             : 
     236         220 :     static size_t word_bitlength(word a){
     237         506 :         for (int i = word_bits() - 1; i >= 0; i--) if ((a >> i) & 1) return i+1;
     238           0 :         return 0;
     239             :     }
     240             : 
     241             :     static size_t word_count_trailing_zeros(word a){
     242             :         for (int i = 0; i < (int)word_bits(); i++) if ((a >> i) & 1) return i;
     243             :         return word_bits();
     244             :     }
     245             : 
     246       16200 :     static word add_carry(word *a, word b){
     247       16200 :         return (*a += b) < b;
     248             :     }
     249             : 
     250        2912 :     static word sub_carry(word *a, word b){
     251        2912 :         word tmp = *a;
     252        2912 :         return (*a = tmp - b) > tmp;
     253             :     }
     254             : 
     255        6400 :     static word word_mul_hi(word a, word b){
     256        6400 :         size_t n = word_bits()/2;
     257        6400 :         word a_hi = a >> n;
     258        6400 :         word a_lo = a & word_half_mask();
     259        6400 :         word b_hi = b >> n;
     260        6400 :         word b_lo = b & word_half_mask();
     261        6400 :         word tmp = ((a_lo*b_lo) >> n) + a_hi*b_lo;
     262        6400 :         tmp = (tmp >> n) + ((a_lo*b_hi + (tmp & word_half_mask())) >> n);
     263        6400 :         return tmp + a_hi*b_hi;
     264             :     }
     265             : 
     266         100 :     static Num& add_unsigned_overwrite(Num &a, const Num &b){
     267         100 :         size_t i, na = a.size(), nb = b.size(), n = std::max(na, nb);
     268         100 :         a.resize(n);
     269         100 :         word carry = 0;
     270        1800 :         for (i = 0; i < nb; i++){
     271        1700 :             carry  = add_carry(&a[i], carry);
     272        1700 :             carry += add_carry(&a[i], b[i]);
     273             :         }
     274         100 :         for (; i < n && carry; i++) carry = add_carry(&a[i], carry);
     275         100 :         if (carry) a.push_back(carry);
     276         200 :         return a.truncate();
     277             :     }
     278             : 
     279         182 :     static Num& sub_unsigned_overwrite(Num &a, const Num &b){
     280             :         //assert(cmp_abs(a, b) >= 0);
     281         182 :         size_t i, na = a.size(), nb = b.size();
     282         182 :         word carry = 0;
     283        1638 :         for (i = 0; i < nb; i++){
     284        1456 :             carry  = sub_carry(&a[i], carry);
     285        1456 :             carry += sub_carry(&a[i], b[i]);
     286             :         }
     287         182 :         for (; i < na && carry; i++) carry = sub_carry(&a[i], carry);
     288             :         //assert(!carry);
     289         182 :         return a.truncate();
     290             :     }
     291             : 
     292         100 :     static Num mul_long(const Num &a, const Num &b){
     293         100 :         size_t na = a.size(), nb = b.size(), nc = na + nb + 1;
     294         100 :         Num c(nc, 0, a.neg ^ b.neg), carries(nc, 0);
     295         900 :         for (size_t ia = 0; ia < na; ia++){
     296        7200 :             for (size_t ib = 0; ib < nb; ib++){
     297        6400 :                 size_t i = ia + ib, j = i + 1;
     298             :                 // WARNING: Might overflow if word size is chosen too small
     299        6400 :                 carries[i + 1] += add_carry(&c[i], a[ia] * b[ib]);
     300        6400 :                 carries[j + 1] += add_carry(&c[j], word_mul_hi(a[ia], b[ib]));
     301             :             }
     302             :         }
     303         200 :         return add_unsigned_overwrite(c, carries).truncate();
     304         100 :     }
     305             : 
     306           0 :     static Num mul_karatsuba(const Num &a, const Num &b){
     307           0 :         size_t na = a.size(), nb = b.size(), n = std::max(na, nb), m2 = n/2 + (n & 1);
     308           0 :         Num a_parts[2], b_parts[2];
     309           0 :         split(a, a_parts, 2, m2);
     310           0 :         split(b, b_parts, 2, m2);
     311           0 :         m2 *= word_bits();
     312           0 :         Num z0 = a_parts[0] * b_parts[0];
     313           0 :         Num z1 = (a_parts[0] + a_parts[1]) * (b_parts[0] + b_parts[1]);
     314           0 :         Num z2 = a_parts[1] * b_parts[1];
     315           0 :         Num result = z2;
     316           0 :         result <<= m2;
     317           0 :         result += z1 - z2 - z0;
     318           0 :         result <<= m2;
     319           0 :         result += z0;
     320           0 :         return result;
     321           0 :     }
     322             : 
     323         100 :     static Num mul(const Num &a, const Num &b){
     324         100 :         size_t karatsuba_threshold = 20;
     325         100 :         if (a.size() > karatsuba_threshold && b.size() > karatsuba_threshold){
     326           0 :             return mul_karatsuba(a, b);
     327             :         }
     328         100 :         return mul_long(a, b);
     329             :     }
     330             : 
     331           0 :     static Num add_signed(const Num &a, bool a_neg, const Num &b, bool b_neg){
     332           0 :         if (a_neg == b_neg) return add_unsigned(a, b).set_neg(a_neg);
     333           0 :         if (cmp_abs(a, b) >= 0) return sub_unsigned(a, b).set_neg(a_neg);
     334           0 :         return sub_unsigned(b, a).set_neg(b_neg);
     335             :     }
     336             : 
     337         308 :     Num& operator >>= (size_t n_bits){
     338         308 :         if (n_bits == 0) return *this;
     339         308 :         size_t n_words = n_bits / word_bits();
     340         308 :         if (n_words >= size()){
     341           0 :             resize(0);
     342           0 :             return *this;
     343             :         }
     344         308 :         n_bits %= word_bits();
     345         308 :         if (n_bits == 0){
     346           0 :             for (size_t i = 0; i < size() - n_words; i++){
     347           0 :                 (*this)[i] = (*this)[i + n_words];
     348             :             }
     349             :         }else{
     350         308 :             word hi, lo = (*this)[n_words];
     351        2464 :             for (size_t i = 0; i < size() - n_words - 1; i++){
     352        2156 :                 hi = (*this)[i + n_words + 1];
     353        2156 :                 (*this)[i] = (hi << (word_bits() - n_bits)) | (lo >> n_bits);
     354        2156 :                 lo = hi;
     355             :             }
     356         308 :             (*this)[size() - n_words - 1] = lo >> n_bits;
     357             :         }
     358         308 :         resize(size() - n_words);
     359         308 :         return truncate();
     360             :     }
     361             : 
     362         110 :     Num& operator <<= (size_t n_bits){
     363         110 :         if (n_bits == 0) return *this;
     364          80 :         size_t n_words = n_bits / word_bits();
     365          80 :         n_bits %= word_bits();
     366          80 :         size_t old_size = size();
     367          80 :         size_t n = old_size + n_words + (n_bits != 0);
     368          80 :         resize(n);
     369          80 :         if (n_bits == 0){
     370           0 :             for (size_t i = n; i --> n_words;){
     371           0 :                 (*this)[i] = (*this)[i - n_words];
     372             :             }
     373             :         }else{
     374          80 :             word lo, hi = 0;
     375         720 :             for (size_t i = n - 1; i > n_words; i--){
     376         640 :                 lo = (*this)[i - n_words - 1];
     377         640 :                 (*this)[i] = (hi << n_bits) | (lo >> (word_bits() - n_bits));
     378         640 :                 hi = lo;
     379             :             }
     380          80 :             (*this)[n_words] = hi << n_bits;
     381             :         }
     382          80 :         for (size_t i = 0; i < n_words; i++) (*this)[i] = 0;
     383          80 :         return truncate();
     384             :     }
     385             : 
     386         200 :     static void div_mod(const Num &numerator, Num denominator, Num &quotient, Num &remainder){
     387         200 :         quotient = 0;
     388         200 :         remainder = numerator;
     389         200 :         if (cmp_abs(remainder, denominator) >= 0){
     390         110 :             int n = numerator.bitlength() - denominator.bitlength();
     391         110 :             denominator <<= n;
     392         418 :             for (; n >= 0; n--){
     393         308 :                 if (cmp_abs(remainder, denominator) >= 0){
     394         182 :                     sub_unsigned_overwrite(remainder, denominator);
     395         182 :                     quotient.set_bit(n);
     396             :                 }
     397         308 :                 denominator >>= 1;
     398             :             }
     399             :         }
     400         200 :         quotient.set_neg(numerator.neg ^ denominator.neg);
     401         200 :         remainder.set_neg(numerator.neg);
     402         200 :     }
     403             : 
     404             :     static void div_mod_half_word(const Num &numerator, word denominator, Num &quotient, word &remainder){
     405             :         remainder = 0;
     406             :         Num dst(numerator.size(), 0);
     407             : 
     408             :         for (size_t i = numerator.size(); i --> 0;){
     409             :             word dst_word = 0;
     410             :             word src_word = numerator[i];
     411             :             word parts[2];
     412             :             parts[0] = src_word >> word_bits()/2;
     413             :             parts[1] = src_word & word_half_mask();
     414             : 
     415             :             for (size_t j = 0; j < 2; j++){
     416             :                 remainder <<= word_bits()/2;
     417             :                 remainder |= parts[j];
     418             : 
     419             :                 word div_word = remainder / denominator;
     420             :                 word mod_word = remainder % denominator;
     421             :                 remainder = mod_word;
     422             : 
     423             :                 dst_word <<= word_bits()/2;
     424             :                 dst_word |= div_word;
     425             :             }
     426             : 
     427             :             dst[i] = dst_word;
     428             :         }
     429             : 
     430             :         quotient = dst.truncate().set_neg(numerator.neg);
     431             :     }
     432             : 
     433           0 :     static void split(const Num &a, Num *parts, size_t n_parts, size_t n){
     434           0 :         size_t i = 0;
     435           0 :         for (size_t k = 0; k < n_parts; k++){
     436           0 :             Num &part = parts[k];
     437           0 :             part.resize(n);
     438           0 :             for (size_t j = 0; j < n && i < a.size(); j++) part[j] = a[i++];
     439           0 :             part = part.truncate();
     440             :         }
     441           0 :     }
     442             : 
     443         100 :     static Num div(const Num &numerator, const Num& denominator){
     444         100 :         Num quotient, remainder;
     445         100 :         div_mod(numerator, denominator, quotient, remainder);
     446         200 :         return quotient;
     447         100 :     }
     448             : 
     449         100 :     static Num mod(const Num &numerator, const Num& denominator){
     450         100 :         Num quotient, remainder;
     451         100 :         div_mod(numerator, denominator, quotient, remainder);
     452         200 :         return remainder;
     453         100 :     }
     454             : 
     455           0 :     static Num add_unsigned(const Num &a, const Num &b){
     456           0 :         Num result(a);
     457           0 :         return add_unsigned_overwrite(result, b);
     458           0 :     }
     459             : 
     460           0 :     static Num sub_unsigned(const Num &a, const Num &b){
     461           0 :         Num result(a);
     462           0 :         return sub_unsigned_overwrite(result, b);
     463           0 :     }
     464             : 
     465           0 :     static Num add(const Num &a, const Num &b){
     466           0 :         Num result = add_signed(a, a.neg, b, b.neg);
     467           0 :         return result;
     468             :     }
     469             : 
     470           0 :     static Num sub(const Num &a, const Num &b){
     471           0 :         Num result = add_signed(a, a.neg, b, !b.neg);
     472           0 :         return result;
     473             :     }
     474             : 
     475             :     static Num gcd(const Num &a0, const Num &b0){
     476             : 
     477             :         if (a0.size() == 1 && b0.size() == 1){
     478             :             return Num(1, word_gcd(a0[0], b0[0]));
     479             :         }
     480             : 
     481             :         Num a(a0), b(b0);
     482             :         a.neg = b.neg = false;
     483             : 
     484             :         if (a.size() == 0) return b0;
     485             :         if (b.size() == 0) return a0;
     486             : 
     487             :         size_t n = a.count_trailing_zeros();
     488             :         size_t m = b.count_trailing_zeros();
     489             :         if (n > m) {
     490             :             std::swap(n, m);
     491             :             a.words.swap(b.words);
     492             :         }
     493             : 
     494             :         a >>= n;
     495             :         b >>= n;
     496             : 
     497             :         do {
     498             :             b >>= b.count_trailing_zeros();
     499             :             if (cmp_abs(a, b) > 0) a.words.swap(b.words);
     500             :             sub_unsigned_overwrite(b, a);
     501             :         } while (b.size() > 0);
     502             : 
     503             :         a <<= n;
     504             : 
     505             :         return a;
     506             :     }
     507             : 
     508             :     typedef void (*random_func)(uint8_t *bytes, size_t n_bytes);
     509             : 
     510             :     static Num random_bits(size_t n_bits, random_func func){
     511             :         if (n_bits == 0) return 0;
     512             :         size_t partial_bits = n_bits % word_bits();
     513             :         size_t n_words = n_bits / word_bits() + (partial_bits > 0);
     514             :         size_t n_bytes = n_words*sizeof(word);
     515             :         Num result(n_words, 0);
     516             :         uint8_t *bytes = (uint8_t*)&result[0];
     517             :         func(bytes, n_bytes);
     518             :         if (partial_bits){
     519             :             size_t too_many_bits = word_bits() - partial_bits;
     520             :             result.back() >>= too_many_bits;
     521             :         }
     522             :         return result;
     523             :     }
     524             : 
     525             :     static Num random_inclusive(const Num &inclusive, random_func func){
     526             :         size_t n_bits = inclusive.bitlength();
     527             :         while (true){
     528             :             Num result = random_bits(n_bits, func);
     529             :             if (result <= inclusive) return result;
     530             :         }
     531             :     }
     532             : 
     533             :     static Num random_exclusive(const Num &exclusive, random_func func){
     534             :         size_t n_bits = exclusive.bitlength();
     535             :         while (true){
     536             :             Num result = random_bits(n_bits, func);
     537             :             if (result < exclusive) return result;
     538             :         }
     539             :     }
     540             : 
     541             :     static Num random_second_exclusive(const Num &inclusive_min_val, const Num &exclusive_max_val, random_func func){
     542             :         return inclusive_min_val + random_exclusive(exclusive_max_val - inclusive_min_val, func);
     543             :     }
     544             : 
     545             :     static Num random_both_inclusive(const Num &inclusive_min_val, const Num &inclusive_max_val, random_func func){
     546             :         return inclusive_min_val + random_inclusive(inclusive_max_val - inclusive_min_val, func);
     547             :     }
     548             : 
     549         182 :     Num& set_bit(size_t i){
     550         182 :         size_t i_word = i / word_bits();
     551         182 :         size_t i_bit =  i % word_bits();
     552         182 :         if (size() <= i_word) resize(i_word + 1);
     553         182 :         (*this)[i_word] |= ((word)1) << i_bit;
     554         182 :         return *this;
     555             :     }
     556             : 
     557             :     word get_bit(size_t i) const {
     558             :         size_t i_word = i / word_bits();
     559             :         size_t i_bit =  i % word_bits();
     560             :         if (i_word >= size()) return 0;
     561             :         return ((*this)[i_word] >> i_bit) & 1;
     562             :     }
     563             : 
     564             :     void clr_bit(size_t i){
     565             :         size_t i_word = i / word_bits();
     566             :         size_t i_bit =  i % word_bits();
     567             :         if (i_word >= size()) return;
     568             :         word mask = 1;
     569             :         mask <<= i_bit;
     570             :         (*this)[i_word] &= ~mask;
     571             :     }
     572             : 
     573             :     Num& mul_word(word b){
     574             :         word carry = 0;
     575             :         for (size_t i = 0; i < size(); i++){
     576             :             word a = (*this)[i];
     577             :             word tmp = a * b;
     578             :             carry = add_carry(&tmp, carry);
     579             :             carry += word_mul_hi(a, b);
     580             :             (*this)[i] = tmp;
     581             :         }
     582             :         if (carry) push_back(carry);
     583             :         return truncate();
     584             :     }
     585             : 
     586             :     Num& add_word(word carry, size_t i0 = 0){
     587             :         if (i0 >= size()) resize(i0 + 1);
     588             :         for (size_t i = i0; i < size() && carry; i++){
     589             :             carry = add_carry(&(*this)[i], carry);
     590             :         }
     591             :         if (carry) push_back(carry);
     592             :         return truncate();
     593             :     }
     594             : 
     595             :     void print(
     596             :         std::vector<char> &text,
     597             :         word base = 10,
     598             :         const char *alphabet = "0123456789abcdefghijklmnopqrstuvwxyz"
     599             :     ) const {
     600             :         if (size() == 0){
     601             :             text.push_back('0');
     602             :         }else{
     603             :             Num tmp(*this);
     604             :             while (tmp.size() > 0){
     605             :                 word remainder;
     606             :                 div_mod_half_word(tmp, base, tmp, remainder);
     607             :                 text.push_back(alphabet[remainder]);
     608             :             }
     609             :             if (neg) text.push_back('-');
     610             :             std::reverse(text.begin(), text.end());
     611             :         }
     612             :         text.push_back('\0');
     613             :     }
     614             : 
     615             :     double to_double() const {
     616             :         if (size() == 0) return 0.0;
     617             :         double d = 0.0, base = ::pow(2.0, word_bits());
     618             :         for (size_t i = size(); i --> 0;) d = d * base + (*this)[i];
     619             :         return neg ? -d : d;
     620             :     }
     621             :     
     622             :     bool can_convert_to_int(int *result){
     623             :         if (*this < Num(INT_MIN) || *this > Num(INT_MAX)) return false;
     624             :         
     625             :         unsigned temp = 0;
     626             :         
     627             :         for (size_t i = words.size(); i --> 0;){
     628             :             temp <<= word_bits();
     629             :             temp += (*this)[i];
     630             :         }
     631             :         
     632             :         *result = neg ? -temp : temp;
     633             :         
     634             :         return true;
     635             :     }
     636             : 
     637             :     Num pow(size_t exponent) const {
     638             :         Num result(1), p(*this);
     639             :         for (; exponent; exponent >>= 1){
     640             :             if (exponent & 1){
     641             :                 result = result * p;
     642             :                 exponent--;
     643             :             }
     644             :             p = p*p;
     645             :         }
     646             :         return result;
     647             :     }
     648             : 
     649             :     Num mod_pow(Num exponent, const Num &modulus) const {
     650             :         Num result(1), base = (*this) % modulus;
     651             :         for (; exponent.size() > 0; exponent >>= 1){
     652             :             if (exponent.get_bit(0)){
     653             :                 result = (result * base) % modulus;
     654             :             }
     655             :             base = (base * base) % modulus;
     656             :         }
     657             :         return result;
     658             :     }
     659             : 
     660             :     Num sqrt() const {
     661             :         Num n = *this;
     662             :         int bit = bitlength();
     663             :         if (bit & 1) bit ^= 1;
     664             :         Num result = 0;
     665             :         for (; bit >= 0; bit -= 2){
     666             :             Num tmp = result;
     667             :             tmp.set_bit(bit);
     668             :             if (n >= tmp){
     669             :                 n -= tmp;
     670             :                 result.set_bit(bit + 1);
     671             :             }
     672             :             result >>= 1;
     673             :         }
     674             :         return result;
     675             :     }
     676             : 
     677             :     Num& operator ++(){
     678             :         add_word(1);
     679             :         return *this;
     680             :     }
     681             : 
     682           0 :     Num& operator += (const Num &b){ return *this = add(*this, b); }
     683             :     Num& operator -= (const Num &b){ return *this = sub(*this, b); }
     684             :     Num& operator *= (const Num &b){ return *this = mul(*this, b); }
     685             :     Num& operator /= (const Num &b){ return *this = div(*this, b); }
     686             :     Num& operator %= (const Num &b){ return *this = mod(*this, b); }
     687             : 
     688             :     bool operator == (const Num &b) const { return cmp(*this, b) == 0; }
     689             :     bool operator != (const Num &b) const { return cmp(*this, b) != 0; }
     690             :     bool operator <= (const Num &b) const { return cmp(*this, b) <= 0; }
     691             :     bool operator >= (const Num &b) const { return cmp(*this, b) >= 0; }
     692             :     bool operator <  (const Num &b) const { return cmp(*this, b) <  0; }
     693             :     bool operator >  (const Num &b) const { return cmp(*this, b) >  0; }
     694             : 
     695           0 :     Num operator + (const Num &b) const { return add(*this, b); }
     696           0 :     Num operator - (const Num &b) const { return sub(*this, b); }
     697         100 :     Num operator * (const Num &b) const { return mul(*this, b); }
     698         100 :     Num operator / (const Num &b) const { return div(*this, b); }
     699         100 :     Num operator % (const Num &b) const { return mod(*this, b); }
     700             :     Num operator - (            ) const { return Num(*this).set_neg(!neg); }
     701             : 
     702             :     Num operator >> (size_t n_bits) const { return Num(*this) >>= n_bits; }
     703             :     Num operator << (size_t n_bits) const { return Num(*this) <<= n_bits; }
     704             : };
     705             : 
     706             : //#pragma GCC diagnostic pop
     707             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.14

Snap C++ | List of projects | List of versions