/* ****************************************************************************
*
* Copyright 2013 Nedim Srndic
*
* This file is part of rsa - the RSA implementation in C++.
*
* rsa is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* rsa is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with rsa. If not, see .
*
* BigInt.h
*
* Author: Nedim Srndic
* Release date: 14th of March 2008
*
* A class representing a positive or negative integer that may
* be too large to fit in any of the standard C++ integer types
* (i. e. 2^128 is "just" 39 digits long).
* The digits are stored in a dinamic array of tipe unsigned char*,
* with values from 0 to 9 (not '0' to '9'), so that the CPU can
* add/subtract individual digits.
*
* The array has "length" memory locations, one byte each (the size of
* unsigned char is probably one byte). There are "digitCount" digits actually
* in use, the rest is spare space.
* The number of digits is constrained by available memory and the limit of the
* unsigned long int type used for indexing (the "length" property).
* The individual digits are stored right-to-left, to speed up computing and
* allow for faster growth of numbers (no need to reallocate memory when
* the digitCount grows).
*
* The class handles its own memory management. There are no memory leaks
* reported until this date.
* When creating a BigInt from const char* or unsigned long int,
* copying from an other BigInt with (digitCount + 2 <= length)
* (soon to be full), new memory is allocated and
* length is adjusted to (length * FACTOR + 1). This is done to expand the
* capacity of the digits array to accomodate potential new digits.
* When assigning a BigInt "bInt" that is twice as small or bigger than *this,
* the length is set to (bInt.length + 2).
*
* BigInt supports:
*
* - addition (unary +, binary +, +=, prefix ++, postfix ++)
*
* - subtraction (unary -, binary -, -=, prefix --, postfix --)
*
* - multiplication (*, *=)
* For multiplication, one can choose between the Square and multiply
* or Karatsuba algorithm, or long multiplication at compile time
* (this can be done by defining or undefining the macro "KARATSUBA"
* in BigInt.cpp).
* The Karatsuba algorithm multiplies integers in O(n^log2(3))
* complexity. log2(3) is approximately 1.585, so this should be
* significantly faster than long multiplication, if the numbers are
* big enough. Currently, the long multiplication is better implemented,
* and runs faster than the Karatsuba multiplication for numbers shorter
* than about 100 digits.
*
* - C-style integer division (/, /=)
*
* - C-style integer division remainder (%, %=)
* When calculating the remainder, the number is first divided.
*
* - comparison (==, !=, <, <=, >, >=)
* All of the <, <=, >, >= operators are equally fast.
*
* - exponentiation (GetPower(), SetPower(), GetPowerMod(), SetPowerMod())
* For exponentiation, the Exponantiation by squaring
* (or Square and multiply or Binary exponentiation) algorithm is used.
* It uses O(log(n)) multiplications and therefore is significantly faster
* than multiplying x with itself n-1 times.
*
* In addition to mathematical operations, BigInt supports:
*
* - automatic conversion from const char *, std::string and unsigned long int
* - safe construction, copying, assignment and destruction
* - automatic conversion to std::string
* - writing to the standard output (operator <<(std::ostream, BigInt))
* - reading from the standard input (operator >>(std::istream, BigInt))
* - getting and setting individual digits (GetDigit(), SetDigit())
* - returning the number of digits (Length())
* - returning a string of digits (ToString())
* This can be useful for human-readable output.
* - returning a value indicating wether the number is odd (IsOdd())
* - returning a value indicating wether the number is positive (IsPositive())
* - returning a value indicating wether the BigInt equals zero (EqualsZero())
* The fastest way to determine this.
* - returning absolute value (Abs())
*
* There are a few static constants defined in this file:
*
* - BigIntZero : a zero of type BigInt
* If you need a zero fast, use this.
* - BigIntOne : a one of type BigInt
* If you need a one fast, use this.
*
* ****************************************************************************
*/
#ifndef BIGINT_H_
#define BIGINT_H_
#include //ostream, istream
#include //sqrt()
#include //ToString(), BigInt(std::string)
class BigInt
{
private:
/* An array of digits stored right to left,
* i.e. int 345 = unsigned char {[5], [4], [3]} */
unsigned char *digits;
// The total length of the allocated memory
unsigned long int length;
// Number of digits
unsigned long int digitCount;
// Sign
bool positive;
/* Multiplication factor for the length property
* when creating or copying objects. */
static const double FACTOR;
/* Transforms the number from unsigned long int to unsigned char[]
* and pads the result with zeroes. Returns the number of digits. */
static unsigned long int int2uchar( unsigned long int number,
unsigned char *digits,
unsigned long int padding);
/* Converts ASCII digits to equivalent unsigned char numeric values. */
static void char2uchar( unsigned char *array,
unsigned long int length);
/* Check if all ASCII values are digits '0' to '9'. */
static bool allCharsAreDigits( const char *array,
unsigned long int length);
/* Compares two BigInt. If the last two arguments are
* omitted, the comparison is sign-insensitive (comparison by
* absolute value). Returns 0 if a == b, 1 if a > b, 2 if a < b. */
static int compareNumbers( unsigned char *a, unsigned long int na,
unsigned char *b, unsigned long int nb,
bool aPositive = true,
bool bPositive = true);
/* Multiplies two unsigned char[] using the Divide and Conquer
* a.k.a. Karatsuba algorithm .*/
static void karatsubaMultiply( unsigned char *a, unsigned char *b,
unsigned long int n,
unsigned char *buffer);
/* Multiplies two unsigned char[] the long way. */
static void longMultiply( unsigned char *a, unsigned long int na,
unsigned char *b, unsigned long int nb,
unsigned char *result);
/* Simple addition, used by the multiply function.
* Returns the remaining carry. */
static unsigned char quickAdd( unsigned char *a, unsigned char *b,
unsigned long int n);
/* Simple subtraction, used by the multiply function. */
static void quickSub( unsigned char *a, unsigned char *b,
unsigned char *end, unsigned long int n);
/* Divides two BigInt numbers. */
static void divide( const BigInt ÷nd, const BigInt &divisor,
BigInt "ient, BigInt &remainder);
/* Returns the value of the specified unsigned char[] as long int. */
static unsigned long int toInt(unsigned char *digits, int n);
/* Saves the sum of two unsigned char* shorter and longer into result.
* It must be nShorter <= nLonger. If doFill == true, it fills the
* remaining free places with zeroes (used in KaratsubaMultiply()).
* Returns true if there was an overflow at the end (meaning that
* the result.digitCount was longer.digitCount + 1. */
static bool add(unsigned char *shorter, unsigned long int nShorter,
unsigned char *longer, unsigned long int nLonger,
unsigned char *result, int nResult,
bool doFill = true);
/* Shifts the digits n places left. */
BigInt &shiftLeft(unsigned long int n);
/* Shifts the digits n places right. */
BigInt &shiftRight(unsigned long int n);
/* Expands the digits* to n. */
void expandTo(unsigned long int n);
public:
BigInt();
BigInt(const char *charNum);
BigInt(unsigned long int intNum);
BigInt(const std::string &str);
BigInt(const BigInt &number);
BigInt &operator =(const BigInt &rightNumber);
~BigInt();
operator std::string() const;
friend std::ostream &operator <<( std::ostream &cout,
const BigInt &number);
friend std::istream &operator >>( std::istream &cin,
BigInt &number);
friend bool operator <(const BigInt &a, const BigInt &b);
friend bool operator <=(const BigInt &a, const BigInt &b);
friend bool operator >(const BigInt &a, const BigInt &b);
friend bool operator >=(const BigInt &a, const BigInt &b);
friend bool operator ==(const BigInt &a, const BigInt &b);
friend bool operator !=(const BigInt &a, const BigInt &b);
friend BigInt operator + (const BigInt &a, const BigInt &b);
BigInt &operator+();
BigInt &operator++();
BigInt operator++(int);
BigInt &operator+=(const BigInt &number);
BigInt operator-() const;
friend BigInt operator-(const BigInt &a, const BigInt &b);
BigInt &operator--();
BigInt operator--(int);
BigInt &operator-=(const BigInt &number);
friend BigInt operator*(const BigInt &a, const BigInt &b);
BigInt &operator*=(const BigInt &number);
friend BigInt operator/(const BigInt &a, const BigInt &b);
BigInt &operator/=(const BigInt &number);
friend BigInt operator%(const BigInt &a, const BigInt &b);
BigInt &operator%=(const BigInt &number);
/* Returns *this to the power of n
* using the fast Square and Multiply algorithm. */
BigInt GetPower(unsigned long int n) const;
/* *this = *this to the power of n. */
void SetPower(unsigned long int n);
/* Returns *this to the power of n
* using the fast Square and Multiply algorithm. */
BigInt GetPower(BigInt n) const;
/* *this = *this to the power of n. */
void SetPower(BigInt n);
/* Returns (*this to the power of b) mod n. */
BigInt GetPowerMod(const BigInt &b, const BigInt &n) const;
/* *this = (*this to the power of b) mod n. */
void SetPowerMod(const BigInt &b, const BigInt &n);
/* Returns the 'index'th digit (zero-based, right-to-left). */
unsigned char GetDigit(unsigned long int index) const;
/* Sets the value of 'index'th digit
* (zero-based, right-to-left) to 'value'. */
void SetDigit(unsigned long int index, unsigned char value);
/* Returns the number of digits. */
unsigned long int Length() const;
/* Returns true if *this is positive, otherwise false. */
bool IsPositive() const;
/* Returns true if *this is odd, otherwise false. */
bool IsOdd() const;
/* Returns the value of BigInt as std::string. */
std::string ToString(bool forceSign = false) const;
/* Returns a value indicating whether *this equals 0. */
bool EqualsZero() const;
/* Returns the absolute value. */
BigInt Abs() const;
};
inline BigInt::~BigInt()
{
delete[] digits;
}
inline BigInt &BigInt::operator+()
{
return *this;
}
/* Returns the number of digits. */
inline unsigned long int BigInt::Length() const
{
return digitCount;
}
/* Returns true if *this is positive, otherwise false. */
inline bool BigInt::IsPositive() const
{
return positive;
}
/* Returns true if *this is odd, otherwise false. */
inline bool BigInt::IsOdd() const
{
return digits[0] & 1;
}
/* Returns a value indicating whether *this equals 0. */
inline bool BigInt::EqualsZero() const
{
return digitCount == 1 && digits[0] == 0;
}
// A BigInt number with the value of 0.
static const BigInt BigIntZero;
// A BigInt number with the value of 1.
static const BigInt BigIntOne(1L);
#endif /*BIGINT_H_*/