Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <functional>
- #include <iostream>
- #include <string>
- #include <algorithm>
- #include <vector>
- #include <iterator>
- #include <stdexcept>
- #include <cstring>
- #include <cstdio>
- #include <cassert>
- #if defined(_MSC_VER) && _MSC_VER < 1600
- typedef unsigned __int32 uint32_t;
- typedef unsigned __int64 uint64_t;
- #else
- #include <stdint.h>
- #endif
- struct BigInt {
- typedef std::vector<uint32_t> cont_type;
- typedef cont_type::iterator cont_iter;
- typedef cont_type::const_iterator cont_const_iter;
- typedef cont_type::reverse_iterator cont_riter;
- typedef cont_type::const_reverse_iterator cont_const_riter;
- BigInt(uint32_t val = 0): data() {
- if (val != 0)
- data.push_back(val);
- }
- BigInt(const std::string& val) throw(std::invalid_argument): data() {
- char buf[16] = {};
- char* p = NULL;
- std::string::const_iterator it;
- for (it = val.begin(); std::distance(it, val.end()) >= 9; it += 9) {
- (*this) *= 1000000000;
- std::memcpy(buf, &*it, 9);
- uint32_t num = std::strtoul(buf, &p, 10);
- if (p != buf + 9)
- throw std::invalid_argument("invalid number");
- *this += num;
- }
- if (it == val.end())
- return;
- size_t d = std::distance(it, val.end());
- std::memcpy(buf, &*it, d + 1);
- uint32_t num = std::strtoul(buf, &p, 10);
- if (p != &buf[d])
- throw std::invalid_argument("invalid number");
- int times = 1;
- while (d--)
- times *= 10;
- (*this) *= times;
- (*this) += num;
- }
- BigInt(const std::string& val, uint32_t rdx): data() {
- for (std::string::const_iterator it = val.begin(); it != val.end(); ++it) {
- (*this) *= rdx;
- uint32_t num = *it > '9' ? *it - '0' : *it + 9 - 'A';
- (*this) += num;
- }
- }
- BigInt& operator +=(uint32_t val) {
- if (data.empty())
- data.assign(1, val);
- else {
- uint64_t result = (uint64_t)data.front() + val;
- data.front() = (uint32_t)result;
- if ( (uint32_t)(result >> (sizeof(uint32_t) * 8)) != 0 ) {
- for (cont_iter pThis = data.begin() + 1; *pThis += 1, *pThis == 0; ++pThis) {
- if (pThis == data.end()) {
- data.push_back(1);
- break;
- }
- }
- }
- }
- return *this;
- }
- static BigInt fromHexString(const std::string& val) throw (std::invalid_argument) {
- BigInt result;
- char buf[16] = {};
- char* p = NULL;
- std::string::const_iterator it = val.begin();
- if (size_t len = val.size() % 8) {
- memcpy(buf, &*it, val.size() % 8);
- uint32_t num = strtoul(buf, &p, 16);
- if (size_t(p - buf) != len)
- throw std::invalid_argument("invalid hex number");
- result.data.push_back(num);
- it += len;
- }
- for (; it != val.end(); it += 8) {
- memcpy(buf, &*it, 8);
- uint32_t num = strtoul(buf, &p, 16);
- if (size_t(p - buf) != 8)
- throw std::invalid_argument("invalid hex number");
- result.data.push_back(num);
- }
- return result;
- }
- BigInt& operator +=(const BigInt& rhs) {
- // It seems that it's safe when this == &rhs;
- if (data.size() < rhs.data.size())
- data.resize(rhs.data.size());
- uint32_t carry = 0;
- cont_iter pThis = data.begin();
- for (cont_const_iter pRhs = rhs.data.begin(); pRhs != rhs.data.end(); ++pRhs, ++pThis) {
- uint64_t result = (uint64_t)*pThis + *pRhs + carry;
- *pThis = (uint32_t)result;
- carry = (uint32_t)(result >> (sizeof(uint32_t) * 8));
- }
- if (carry != 0) {
- for (; *pThis += 1, *pThis == 0; ++pThis) {
- if (pThis == data.end()) {
- data.push_back(1);
- break;
- }
- }
- }
- return *this;
- }
- BigInt& operator *=(uint32_t val) {
- if (!data.empty()) {
- if (val == 0) {
- data.clear();
- } else {
- uint32_t carry = 0;
- for (cont_iter pThis = data.begin(); pThis != data.end(); ++pThis) {
- uint64_t result = (uint64_t)*pThis * val + carry;
- *pThis = (uint32_t)result;
- carry = (uint32_t)(result >> (sizeof(uint32_t) * 8));
- }
- if (carry != 0)
- data.push_back(carry);
- }
- }
- return *this;
- }
- BigInt& operator *=(const BigInt& val) {
- if (this == &val)
- return (*this) *= BigInt(val);
- BigInt multiplier, temp;
- multiplier.data.reserve(val.data.size() + data.size());
- multiplier = *this;
- data.clear();
- data.reserve(val.data.size() + data.size());
- for (cont_const_iter pThis = val.data.begin(); pThis != val.data.end(); ++pThis) {
- *this += ((temp = multiplier) *= *pThis);
- multiplier.data.insert(multiplier.data.begin(), 0);
- }
- return *this;
- }
- BigInt& operator /=(uint32_t val) throw(std::invalid_argument) {
- if (val == 0)
- throw std::invalid_argument("Divided by zero");
- uint32_t carry = 0;
- for (cont_riter pThis = data.rbegin(); pThis != data.rend(); ++pThis) {
- uint64_t result = *pThis + ((uint64_t)carry << (sizeof(uint32_t) * 8));
- *pThis = (uint32_t)(result / val);
- carry = (uint32_t)(result % val);
- }
- if (data.back() == 0 && data.size() != 1)
- data.pop_back();
- return *this;
- }
- uint32_t operator %(uint32_t val) const throw(std::invalid_argument) {
- if (val == 0)
- throw std::invalid_argument("Divided by zero");
- uint32_t carry = 0;
- for (cont_const_iter pThis = data.begin(); pThis != data.end(); ++pThis) {
- uint64_t result = *pThis + ((uint64_t)carry << (sizeof(uint32_t) * 8));
- carry = (uint32_t)(result % val);
- }
- return carry;
- }
- #if __cplusplus >= 201103L
- BigInt operator +(uint32_t val) const {
- return BigInt(*this) += val;
- }
- BigInt operator +(const BigInt& rhs) const {
- return BigInt(*this) += rhs;
- }
- BigInt&& operator +=(BigInt&& rhs) const {
- return std::move(rhs += *this);
- }
- BigInt operator *(uint32_t val) const {
- return BigInt(*this) *= val;
- }
- BigInt operator *(const BigInt& rhs) const {
- return BigInt(*this) *= rhs;
- }
- BigInt&& operator *(BigInt&& rhs) const {
- return std::move(rhs *= *this);
- }
- #endif
- bool operator ==(const BigInt& rhs) const {
- return data == rhs.data;
- }
- std::string toString() const {
- BigInt rhs = *this;
- if (rhs.data.empty())
- return "0";
- std::string result;
- char buf[16];
- while (rhs.data.size() != 1) {
- std::sprintf(buf, "%09u", rhs.DivButReturnMod(1000000000));
- result.insert(result.begin(), &buf[0], &buf[9]);
- }
- int num = std::sprintf(buf, "%u", rhs.data[0]);
- result.insert(result.begin(), &buf[0], &buf[num]);
- return result;
- }
- std::string toHexString() const {
- if (data.empty())
- return "0";
- char buf[16];
- std::string result;
- cont_const_iter it = data.begin();
- std::sprintf(buf, "%X", *it);
- result += buf;
- for (++it; it != data.end(); ++it) {
- std::sprintf(buf, "%08X", *it);
- result += buf;
- }
- return result;
- }
- std::string toString(uint32_t rdx) const {
- if (data.empty())
- return "0";
- BigInt rhs = *this;
- std::string result;
- while (rhs.data.size() != 1) {
- uint32_t num = rhs.DivButReturnMod(rdx);
- result.push_back(num > 9 ? num + 'A' - 9 : num + '0');
- }
- std::reverse(result.begin(), result.end());
- return result;
- }
- friend std::ostream& operator <<(std::ostream& os, const BigInt& rhs) {
- return os << rhs.toString();
- }
- friend std::istream& operator >>(std::istream& is, BigInt& rhs) {
- std::string result;
- is >> result;
- try {
- rhs = result;
- } catch (std::invalid_argument&) {
- is.setstate(std::ios_base::badbit);
- }
- return is;
- }
- std::ostream& printData(std::ostream& os) const {
- std::ios_base::fmtflags old = os.setf(std::ios_base::hex, std::ios_base::basefield);
- std::copy(data.begin(), data.end(), std::ostream_iterator<int>(os, " "));
- os.setf(old);
- return os;
- }
- private:
- uint32_t DivButReturnMod(uint32_t val) {
- assert(val != 0);
- uint32_t carry = 0;
- for (cont_riter pThis = data.rbegin(); pThis != data.rend(); ++pThis) {
- uint64_t result = *pThis + ((uint64_t)carry << (sizeof(uint32_t) * 8));
- *pThis = (uint32_t)(result / val);
- carry = (uint32_t)(result % val);
- }
- if (data.back() == 0)
- data.pop_back();
- return carry;
- }
- cont_type data; // little-endian
- #if __cplusplus >= 201103L
- template <int index, int max, char... Nums>
- friend struct B;
- #endif
- };
- #if __cplusplus >= 201103L
- namespace BIStrConvImpl
- {
- template <int index, int i, int Sum, char... Others>
- struct A;
- template <int index, int i, int Sum, char N, char... Others>
- struct A<index, i, Sum, N, Others...> {
- static const int times = A<index, i + 1, Sum, Others...>::times;
- static const int value = A<index, i + 1, Sum, Others...>::value;
- };
- template <int index, int Sum, char N, char... Others>
- struct A<index, 9, Sum, N, Others...> {
- static const int times = A<index - 1, 0, Sum, N, Others...>::times;
- static const int value = A<index - 1, 0, Sum, N, Others...>::value;
- };
- template <int i, int Sum, char N, char... Others>
- struct A<0, i, Sum, N, Others...> {
- static const int times = A<0, i + 1, Sum * 10 + N - '0', Others...>::times * 10;
- static const int value = A<0, i + 1, Sum * 10 + N - '0', Others...>::value;
- };
- template <int Sum, char N, char... Others>
- struct A<0, 9, Sum, N, Others...> {
- static const int times = 1;
- static const int value = Sum;
- };
- template <int i, int Sum>
- struct A<0, i, Sum> {
- static const int times = 1;
- static const int value = Sum;
- };
- template <int index, int max, char... Nums>
- struct B {
- __attribute__((always_inline)) B(BigInt& bi) {
- bi *= A<index, 0, 0, Nums...>::times;
- bi += A<index, 0, 0, Nums...>::value;
- B<index + 1, max, Nums...> temp(bi);
- }
- };
- template <int max, char... Nums>
- struct B<max, max, Nums...> {
- B(BigInt& bi) {}
- };
- }
- template <char... Nums>
- BigInt operator "" _bi() {
- BigInt bi;
- BIStrConvImpl::B<0, sizeof... (Nums) / 9 + (sizeof... (Nums) % 9 == 0 ? 0 : 1), Nums...> temp(bi);
- return bi;
- }
- #endif //cplusplus >= 201103L
- int main() {
- // std::cout << 12345678912345678912345_bi * 54321987654321987654321_bi << std::endl;
- BigInt bi("12345678912345678912345");
- bi *= BigInt("54321987654321987654321");
- std::cout << bi << std::endl;
- std::cout << bi.toHexString() << std::endl;
- std::cout << BigInt::fromHexString("123456ABCDEF").toHexString() << std::endl;
- std::cout << 1_bi * 2_bi * 3_bi * 4_bi;
- }
Advertisement
Add Comment
Please, Sign In to add comment