/* * InfInt - Arbitrary-Precision Integer Arithmetic Library * Copyright (C) 2013 Sercan Tutar * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * * USAGE: * It is pretty straight forward to use the library. Just create an instance of * InfInt class and start using it. * * Useful methods: * intSqrt: integer square root operation * digitAt: returns digit at index * numberOfDigits: returns number of digits * size: returns size in bytes * toString: converts it to a string * * There are also conversion methods which allow conversion to primitive types: * toInt, toLong, toLongLong, toUnsignedInt, toUnsignedLong, toUnsignedLongLong. * * You may define INFINT_USE_EXCEPTIONS and library methods will start raising * InfIntException in case of error instead of writing error messages using * std::cerr. * * See ReadMe.txt for more info. * * * No overflows, happy programmers! * */
inlineint InfInt::toInt() const { //PROFINY_SCOPE if (*this > INT_MAX || *this < INT_MIN) { #ifdef INFINT_USE_EXCEPTIONS throw InfIntException("out of bounds"); #else std::cerr << "Out of INT bounds: " << *this << std::endl; #endif } int result = 0; for (int i = (int) val.size() - 1; i >= 0; --i) { result = result * BASE + val[i]; } return pos ? result : -result; }
inlinelong InfInt::toLong() const { //PROFINY_SCOPE if (*this > LONG_MAX || *this < LONG_MIN) { #ifdef INFINT_USE_EXCEPTIONS throw InfIntException("out of bounds"); #else std::cerr << "Out of LONG bounds: " << *this << std::endl; #endif } long result = 0; for (int i = (int) val.size() - 1; i >= 0; --i) { result = result * BASE + val[i]; } return pos ? result : -result; }
inlinelonglong InfInt::toLongLong() const { //PROFINY_SCOPE if (*this > LONG_LONG_MAX || *this < LONG_LONG_MIN) { #ifdef INFINT_USE_EXCEPTIONS throw InfIntException("out of bounds"); #else std::cerr << "Out of LLONG bounds: " << *this << std::endl; #endif } longlong result = 0; for (int i = (int) val.size() - 1; i >= 0; --i) { result = result * BASE + val[i]; } return pos ? result : -result; }
inlineunsignedint InfInt::toUnsignedInt() const { //PROFINY_SCOPE if (!pos || *this > UINT_MAX) { #ifdef INFINT_USE_EXCEPTIONS throw InfIntException("out of bounds"); #else std::cerr << "Out of UINT bounds: " << *this << std::endl; #endif } unsignedint result = 0; for (int i = (int) val.size() - 1; i >= 0; --i) { result = result * BASE + val[i]; } return result; }
inlineunsignedlong InfInt::toUnsignedLong() const { //PROFINY_SCOPE if (!pos || *this > ULONG_MAX) { #ifdef INFINT_USE_EXCEPTIONS throw InfIntException("out of bounds"); #else std::cerr << "Out of ULONG bounds: " << *this << std::endl; #endif } unsignedlong result = 0; for (int i = (int) val.size() - 1; i >= 0; --i) { result = result * BASE + val[i]; } return result; }
inlineunsignedlonglong InfInt::toUnsignedLongLong() const { //PROFINY_SCOPE if (!pos || *this > ULONG_LONG_MAX) { #ifdef INFINT_USE_EXCEPTIONS throw InfIntException("out of bounds"); #else std::cerr << "Out of ULLONG bounds: " << *this << std::endl; #endif } unsignedlonglong result = 0; for (int i = (int) val.size() - 1; i >= 0; --i) { result = result * BASE + val[i]; } return result; }
inlinevoid InfInt::truncateToBase() { //PROFINY_SCOPE for (size_t i = 0; i < val.size(); ++i) // truncate each { if (val[i] >= BASE || val[i] <= -BASE) { div_t dt = my_div(val[i], BASE); val[i] = dt.rem; if (i + 1 >= val.size()) { val.push_back(dt.quot); } else { val[i + 1] += dt.quot; } } } }
inlinebool InfInt::equalizeSigns() { //PROFINY_SCOPE bool isPositive = true; int i = (int) ((val.size())) - 1; for (; i >= 0; --i) { if (val[i] != 0) { isPositive = val[i--] > 0; break; } }
if (isPositive) { for (; i >= 0; --i) { if (val[i] < 0) { int k = 0, index = i + 1; for (; (size_t)(index) < val.size() && val[index] == 0; ++k, ++index) ; // count adjacent zeros on left //if ((size_t)(index) < val.size() && val[index] > 0) { // number on the left is positive val[index] -= 1; val[i] += BASE; for (; k > 0; --k) { val[i + k] = UPPER_BOUND; } } } } } else { for (; i >= 0; --i) { if (val[i] > 0) { int k = 0, index = i + 1; for (; (size_t)(index) < val.size() && val[index] == 0; ++k, ++index) ; // count adjacent zeros on right //if ((size_t)(index) < val.size() && val[index] < 0) { // number on the left is negative val[index] += 1; val[i] -= BASE; for (; k > 0; --k) { val[i + k] = -UPPER_BOUND; } } } } } return isPositive; }
inlinevoid InfInt::removeLeadingZeros() { //PROFINY_SCOPE for (int i = (int) (val.size()) - 1; i > 0; --i) // remove leading 0's { if (val[i] != 0) { return; } else { val.erase(val.begin() + i); } } }