2018年11月21日 星期三

利用 c++ 運算子(operator)包裝 GMP 成為 bigInteger

//bigint.c 
#include "gmp.h"
#include "stdio.h"
#include "stdarg.h"
struct bigInteger{   
    mpz_t z;
    mpz_t m;
    ~bigInteger()                           { mpz_clear(z);                       }
    bigInteger()                             { mpz_init(z) ;                         }   
    bigInteger(const mpz_t& t)                { mpz_init(z) ; mpz_set(z, t);          }   
    bigInteger(const bigInteger& a)        { mpz_init(z) ; mpz_set(z, a.z);        }   
    bigInteger(const char *str, int base=16){ mpz_init(z) ; mpz_set_str(z, str, base);}// default base 16
    bigInteger& operator += (bigInteger a)  { mpz_add(z, z, a.z); return *this; }
    bigInteger  operator +  (bigInteger a)  {
        bigInteger ans;
        mpz_add(ans.z, z, a.z); 
        return ans; // return new bigInteger
     }
    bigInteger& operator ++ ()      { mpz_add_ui(z, z, 1); return *this;    }// ++ prefix
    bigInteger  operator ++ (int)            { // postfix ++                   
            auto ans = bigInteger(z);             // copy of z
            mpz_add_ui(z, z, 1);                     // self inc 1
            return ans;                                      // return oringal copy
     }
    bigInteger& operator -= (bigInteger a)  { mpz_sub(z, z, a.z); return *this;  }
    bigInteger  operator -  (bigInteger a)  {
        bigInteger ans;
        mpz_sub(ans.z, z, a.z); 
        return ans; // return new bigInteger
     }
    bigInteger& operator -- ()        { mpz_sub_ui(z, z, 1); return *this;}// ++ prefix
    bigInteger  operator -- (int)              { // postfix --                   
            auto ans = bigInteger(z);             // copy of z
            mpz_sub_ui(z, z, 1);                     // self dec 1
            return ans;                                     // return oringal copy
     }
    bigInteger& operator *= (bigInteger a)  { mpz_mul(z, z, a.z); return *this;        }
    bigInteger  operator *  (bigInteger a)  {
        bigInteger ans;
        mpz_mul(ans.z, z, a.z);
        return ans; // return new bigInteger
     }
    bigInteger& operator /= (bigInteger a)  { mpz_tdiv_q(z, z, a.z); return *this;    }
    bigInteger  operator /  (bigInteger a)  {
        bigInteger ans;
        mpz_tdiv_q(ans.z, z, a.z);
        return ans; // return new bigInteger
     }
    bigInteger& operator %= (bigInteger a)  { mpz_mod(z, z, a.z); return *this;        }
    bigInteger  operator %  (bigInteger a)  {
        bigInteger ans;
        mpz_mod(ans.z, z, a.z);
        return ans; // return new bigInteger
     }
 /*  -- todo
    bigInteger& operator ^= (bigInteger a)  { mpz_powm(z, z, a.z, m); return *this;    }
    bigInteger  operator ^  (bigInteger a)  {
        bigInteger ans;
        mpz_powm(ans.z, z, a.z, m);
        return ans; // return new bigInteger
     }
*/
    bigInteger& operator ^=(unsigned long int e){ mpz_pow_ui(z, z, e); return *this;}
    bigInteger  operator ^ (unsigned long int e){
        bigInteger ans;
        mpz_pow_ui(ans.z, z, e);
        return ans; // return new bigInteger
     }
    bigInteger& printf(const char *fmt, ...){ // avoid waring for incorrect type
        va_list args;
        va_start(args, fmt);
        vprintf(fmt, args);
        va_end(args);
        return *this; // method chain if necessary
     }   
    bigInteger& toHex() {// using mpz internal memory alloc
        printf("0x%s\n",mpz_get_str(NULL, 16, z)); //or  gmp_printf("0x%Zd\n",z);
        return *this;
     }
    bigInteger& toDec() { // using mpz internal memory alloc,
        printf("%s\n",mpz_get_str(NULL, 10, z)); //or  gmp_printf("%Zd\n",z);
        return *this;
     }
};
// bool bigInteger::staticflag = false; // prevent waring: forbids in-class initialization of non-const static member
int main(){
  auto a = bigInteger("10", 10); // base 10
  auto b = bigInteger("ABC3"); // base 16
  auto c = b ^ 3;
  c.printf("c=").toDec();
  a.printf("a=").toDec();
  b.printf("b=").toDec();
  (a % b).printf("a %% b = ").toDec();
}
編譯並執行 g++ bigint.c -lgmp  && ./a.out
c=85015678987611
a=10
b=43971
a % b = 10


沒有留言: