FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

GitHub Viewer

// SPDX-License-Identifier: LGPL-3.0-or-later AND MIT // Copyright (C) 2020-2022 - csbiginteger-cpp project #include // // using gmp as internal computation method // TODO(igormcoelho): abandon this in favor of more portable libraries // sudo apt install libgmp (or libgmp-dev) #include #include #include // c++ #include // TODO(igormcoelho): remove // Ported from // - // https://referencesource.microsoft.com/#System.Numerics/System/Numerics/BigInteger.cs // using namespace std; using namespace csbiginteger; // NOLINT // input is raw little-endian format mpz_class csBigIntegerMPZparse(cs_vbyte n); // string parse mpz_class csBigIntegerMPZparses(std::string n, int base); // get bitstring from mpz bignum non-negative object std::string csBigIntegerGetBitsFromNonNegativeMPZ(mpz_class big); // get big-endian bytearray from mpz bignum (positive or negative) cs_vbyte csBigIntegerGetBytesFromMPZ(mpz_class big); // ==================== END MPZ ======================= std::string BigInteger::getEngine() { return "GMP"; } const BigInteger BigInteger::error() { BigInteger big; big._data = cs_vbyte(0); // empty array is error return big; } BigInteger BigInteger::Pow(BigInteger value, int exponent) { // according to C# spec, only non-negative int32 values accepted here if (exponent < 0) return BigInteger::Error(); mpz_class big1 = csBigIntegerMPZparse(value.ToByteArray()); mpz_class r; uint64_t _exp = exponent; mpz_pow_ui(r.get_mpz_t(), big1.get_mpz_t(), _exp); cs_vbyte vr = csBigIntegerGetBytesFromMPZ(r); reverse(vr.begin(), vr.end()); // to little-endian return BigInteger(vr); } // default is base 10 // allows base 2 // if base 16, prefix '0x' indicates big-endian, otherwise is little-endian BigInteger::BigInteger(std::string str, int base) { mpz_class a = csBigIntegerMPZparses(str, base); _data = csBigIntegerGetBytesFromMPZ(a); } BigInteger::BigInteger(float val) { mpz_class a = val; _data = csBigIntegerGetBytesFromMPZ(a); } cs_int32 BigInteger::toInt() const { cs_vbyte vb = this->ToByteArray(); // little-endian mpz_class a = csBigIntegerMPZparse(vb); cs_int32 i = a.get_ui(); // unsigned int if (a < 0) i *= -1; return i; } cs_int64 BigInteger::toLong() const { cs_vbyte vb = this->ToByteArray(); // little-endian mpz_class a = csBigIntegerMPZparse(vb); cs_int64 i = a.get_si(); // signed long int return i; } bool BigInteger::operator>(const BigInteger& big2) const { if (this->IsError() || big2.IsError()) return false; mpz_class bThis = csBigIntegerMPZparse(this->ToByteArray()); // parse from little-endian mpz_class bOther = csBigIntegerMPZparse(big2.ToByteArray()); // parse from little-endian bool r = (bThis > bOther); // result return r; } bool BigInteger::operatorIsError() || big2.IsError()) { return false; } mpz_class bThis = csBigIntegerMPZparse(this->ToByteArray()); // parse from little-endian mpz_class bOther = csBigIntegerMPZparse(big2.ToByteArray()); // parse from little-endian bool r = (bThis < bOther); // result return r; } // ----------------- arithmetic --------------------- BigInteger BigInteger::operator+(const BigInteger& big2) const { if (this->IsError() || big2.IsError()) return Error(); mpz_class bThis = csBigIntegerMPZparse(this->ToByteArray()); // parse from little-endian mpz_class bOther = csBigIntegerMPZparse(big2.ToByteArray()); // parse from little-endian BigInteger r; // result r._data = csBigIntegerGetBytesFromMPZ(bThis + bOther); // get big-endian return r; } BigInteger BigInteger::operator-(const BigInteger& big2) const { if (this->IsError() || big2.IsError()) return Error(); mpz_class bThis = csBigIntegerMPZparse(this->ToByteArray()); // parse from little-endian mpz_class bOther = csBigIntegerMPZparse(big2.ToByteArray()); // parse from little-endian BigInteger r; // result r._data = csBigIntegerGetBytesFromMPZ(bThis - bOther); // get big-endian return r; } BigInteger BigInteger::operator*(const BigInteger& big2) const { if (this->IsError() || big2.IsError()) return Error(); mpz_class bThis = csBigIntegerMPZparse(this->ToByteArray()); // parse from little-endian mpz_class bOther = csBigIntegerMPZparse(big2.ToByteArray()); // parse from little-endian BigInteger r; // result r._data = csBigIntegerGetBytesFromMPZ(bThis * bOther); // get big-endian return r; } BigInteger BigInteger::operator/(const BigInteger& big2) const { if (this->IsError() || big2.IsError() || big2.IsZero()) return Error(); mpz_class bThis = csBigIntegerMPZparse(this->ToByteArray()); // parse from little-endian mpz_class bOther = csBigIntegerMPZparse(big2.ToByteArray()); // parse from little-endian BigInteger r; // result r._data = csBigIntegerGetBytesFromMPZ(bThis / bOther); // get big-endian return r; } BigInteger BigInteger::operator%(const BigInteger& big2) const { if (this->IsError() || big2.IsError() || big2.IsZero()) return Error(); mpz_class bThis = csBigIntegerMPZparse(this->ToByteArray()); // parse from little-endian mpz_class bOther = csBigIntegerMPZparse(big2.ToByteArray()); // parse from little-endian BigInteger r; // result r._data = csBigIntegerGetBytesFromMPZ(bThis % bOther); // get big-endian return r; } BigInteger BigInteger::operator> -big2; mpz_class bThis = csBigIntegerMPZparse(this->ToByteArray()); // parse from little-endian BigInteger r; // result r._data = csBigIntegerGetBytesFromMPZ(bThis >(const BigInteger& big2) const { if (this->IsError() || big2.IsError()) return Error(); if (big2 < Zero()) return (*this) ToByteArray()); // parse from little-endian BigInteger r; // result r._data = csBigIntegerGetBytesFromMPZ(bThis >> big2.toInt()); // get big-endian return r; } // =================== BEGIN MPZ AGAIN ======================= std::string BigInteger::toStringBase10() const { mpz_class bThis = csBigIntegerMPZparse(this->ToByteArray()); // parse from little-endian return bThis.get_str(10); } // assumes big >= 0 std::string csBigIntegerGetBitsFromNonNegativeMPZ(mpz_class big) { std::string sbin; while (big > 0) { mpz_class rest = (big % 2); sbin.insert(0, (rest.get_ui() == 0 ? std::string("0") : std::string("1"))); big = big / 2; } return sbin; } cs_vbyte csBigIntegerGetBytesFromMPZ(mpz_class big) { // check if positive or negative if (big >= 0) { // ------------------- // positive conversion // ------------------- cs_vbyte v; while (big > 0) { mpz_class rest = (big % 256); v.push_back((cs_byte)rest.get_ui()); big = big / 256; } // added in little-endian format (backwards) std::string leHex = Helper::toHexString(v); if (leHex.length() == 0) leHex = "00"; // check if became negative if (Helper::checkNegativeBit(leHex)) { v.push_back(0); // guarantee non-negative } // v is added backwards (little-endian), must reverse (to big-endian) reverse(v.begin(), v.end()); if (v.size() == 0) v.push_back(0x00); // finished return v; } else { // ------------------- // negative conversion // ------------------- // turn into positive mpz_class x = big * (-1); // cout

Back | FazBrowse Home | New Git URL