Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
BigInt.cpp
- Committer:
- feb11
- Date:
- 2013-09-20
- Revision:
- 1:00f2c40d46ed
- Parent:
- 0:9d554894785b
- Child:
- 2:1001793a090d
File content as of revision 1:00f2c40d46ed:
#include "BigInt.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <climits>
static uint32_t max(const uint32_t a, const uint32_t b)
{
return a < b ? b : a;
}
static uint32_t num(const uint32_t a)
{
return a/4 + (a%4 ? 1:0);
}
BigInt::BigInt():
size(0),
bits(0)
{
}
BigInt::BigInt(const BigInt &a):
size(a.size)
{
uint32_t l = num(size);
bits = new uint32_t[l];
for(int i = 0; i < l; ++i)
bits[i] = a.bits[i];
}
BigInt::~BigInt()
{
if(bits)
delete[] bits;
bits = 0;
}
BigInt& BigInt::operator=(const BigInt& a)
{
size = a.size;
uint32_t l = num(size);
if(bits)
delete[] bits;
bits = new uint32_t[l];
for(int i = 0; i < l; ++i)
bits[i] = a.bits[i];
return *this;
}
void BigInt::import(uint8_t *data, uint32_t length)
{
size = length;
size_t l = size/4;
if(size % 4 != 0)
l++;
if(bits)
delete[] bits;
bits = new uint32_t[l];
memset(bits, 0, sizeof(uint32_t)*l);
for(int i = 0; i < length; ++i)
bits[i/4] |= data[i] << ((i%4)*8);
}
BigInt operator+(const BigInt &a, const BigInt& b)
{
BigInt result;
result.size = a.size > b.size ? a.size : b.size;
size_t l = result.size/4;
if(result.size % 4 != 0)
l++;
result.bits = new uint32_t[l];
memset(result.bits, 0, sizeof(uint32_t)*l);
uint32_t al = num(a.size);
uint32_t bl = num(b.size);
uint32_t carry = 0;
for(int i = 0; i < l; ++i)
{
uint32_t tmpA = 0, tmpB = 0;
if(i < al)
tmpA = a.bits[i];
if(i < bl)
tmpB = b.bits[i];
result.bits[i] = tmpA + tmpB + carry;
carry = result.bits[i] < max(tmpA, tmpB);
}
if(carry)
{
result.size++;
if(result.size > l*4)
{
l++;
result.bits = (uint32_t*)realloc(result.bits, l * sizeof(uint32_t));
result.bits[l-1] = 0x00000001;
}
else
{
result.bits[l-1] += 1 << (8 *((result.size-1)%4));
}
}
return result;
}
BigInt& BigInt::operator+=(const BigInt &b)
{
return (*this = (*this) + b);
}
BigInt& BigInt::operator++()
{
uint8_t tmp = 1;
BigInt a;
a.import(&tmp, 1);
return (*this += a);
}
BigInt BigInt::operator++(int)
{
BigInt t = *this;
uint8_t tmp = 1;
BigInt a;
a.import(&tmp, 1);
this->operator+=(a);
return t;
}
// a - b, if b >= a, returns 0
// No negative number allowed
BigInt operator-(const BigInt &a, const BigInt& b)
{
BigInt result;
if(b >= a)
{
uint8_t tmp = 0;
result.import(&tmp, 1);
return result;
}
else
{
result.size = a.size;
uint32_t l = num(a.size);
result.bits = new uint32_t[l];
memset(result.bits, 0, sizeof(uint32_t)*l);
uint32_t bl = num(b.size);
uint8_t borrow = 0;
for(uint32_t i = 0; i < l; ++i)
{
uint32_t tmpA = a.bits[i], tmpB = 0;
if(i < bl)
tmpB = b.bits[i];
if(borrow)
{
if(tmpA == 0)
tmpA = ULONG_MAX;
else
--tmpA;
if(tmpA < tmpB)
result.bits[i] = tmpA + 1 + (ULONG_MAX - tmpB);
else
result.bits[i] = tmpA - tmpB;
if(a.bits[i] != 0 && tmpA > tmpB)
borrow = 0;
}
else
{
if(tmpA < tmpB)
result.bits[i] = tmpA + 1 + (ULONG_MAX - tmpB);
else
result.bits[i] = tmpA - tmpB;
borrow = tmpA < tmpB;
}
}
// trim result
uint8_t *tmp = (uint8_t*)result.bits;
uint32_t newSize = result.size;
while(tmp[newSize-1] == 0 && newSize > 0)
newSize--;
result.size = newSize;
uint32_t tmpL = num(result.size);
if(tmpL < l)
result.bits = (uint32_t*)realloc(result.bits, sizeof(uint32_t)*tmpL);
return result;
}
}
BigInt& BigInt::operator-=(const BigInt &b)
{
return (*this = (*this) - b);
}
BigInt& BigInt::operator--()
{
uint8_t tmp = 1;
BigInt a;
a.import(&tmp, 1);
return (*this -= a);
}
BigInt BigInt::operator--(int)
{
BigInt t = *this;
uint8_t tmp = 1;
BigInt a;
a.import(&tmp, 1);
this->operator-=(a);
return t;
}
/*
BigInt operator*(const BigInt &a, const BigInt& b)
{
BigInt result;
// if a == 0 or b == 0 then result = 0
if(!a || !b)
{
uint8_t tmp = 0;
result.import(&tmp, 1);
return result;
}
uint8_t tmp = 1;
BigInt one;
one.import(&tmp, 1);
// if a == 1, then result = b
if(a == one)
return (result = b);
// if b == 1, then result = a
if(b == one)
return (result = a);
return result;
}
BigInt& BigInt::operator*=(const BigInt &b)
{
return (*this = (*this) * b);
}
*/
BigInt operator>>(const BigInt &a, const uint32_t m)
{
BigInt result;
if(m == 0)
return result = a;
if(m/8 >= a.size)
{
uint8_t tmp = 0;
result.import(&tmp, 0);
return result;
}
result.size = a.size - m/8;
result.bits = new uint32_t[num(result.size)];
uint8_t s = m%32;
for(uint32_t i = 0; i < num(result.size); ++i)
{
if(m/32+i+1 < num(a.size))
result.bits[i] = (a.bits[m/32+i+1] << (32-s)) | (a.bits[m/32+i] >> s);
else
result.bits[i] = (a.bits[m/32+i] >> s);
}
return result;
}
BigInt& BigInt::operator>>=(const uint32_t m)
{
return *this = *this >> m;
}
BigInt operator<<(const BigInt &a, const uint32_t m)
{
BigInt result;
if(m == 0)
return result = a;
result.size = m/8 + a.size;
uint32_t h = a.bits[num(a.size)-1];
if((h << (m%32)) < h)
++result.size;
uint32_t l = num(result.size);
result.bits = new uint32_t[l];
memset(result.bits, 0, sizeof(uint32_t)*l);
uint32_t s = m % 32;
for(uint32_t i = 0; i < num(a.size); ++i)
{
if(i == 0)
result.bits[m/32+i] = a.bits[i] << s;
else
result.bits[m/32+i] = (a.bits[i] << s) | (a.bits[i-1] >> (32-s));
}
if(a.bits[num(a.size)-1] << s < a.bits[num(a.size)-1])
result.bits[num(result.size)-1] = a.bits[num(a.size)-1] >> (32-s);
return result;
}
BigInt& BigInt::operator<<=(const uint32_t m)
{
return (*this = *this << m);
}
bool operator==(const BigInt &a, const BigInt &b)
{
if(a.size != b.size)
return false;
uint32_t l = num(a.size);
for(int i = 0; i < l; ++i)
if(a.bits[i] != b.bits[i])
return false;
return true;
}
bool operator!=(const BigInt &a, const BigInt &b)
{
return ! (a==b);
}
bool operator<(const BigInt &a, const BigInt &b)
{
if(a.size < b.size)
return true;
if(a.size > b.size)
return false;
uint32_t l = num(a.size);
for(int i = l-1; i >= 0; --i)
if(a.bits[i] < b.bits[i])
return true;
return false;
}
bool operator<=(const BigInt &a, const BigInt &b)
{
return (a < b) || (a == b);
}
bool operator>(const BigInt &a, const BigInt &b)
{
if(a.size > b.size)
return true;
if(a.size < b.size)
return false;
uint32_t l = num(a.size);
for(int i = l-1; i >= 0; --i)
if(a.bits[i] > b.bits[i])
return true;
return false;
}
bool operator>=(const BigInt &a, const BigInt &b)
{
return (a > b) || (a == b);
}
bool operator!(const BigInt &a)
{
if(a.size != 1)
return false;
return a.bits[0] == 0;
}
void BigInt::print()
{
printf("size: %d bytes\n", size);
uint32_t n = num(size);
for(int i = n-1; i >= 0; --i)
{
printf("%08x ", bits[i]);
}
printf("\n");
}