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:
- 0:9d554894785b
- Child:
- 1:00f2c40d46ed
File content as of revision 0:9d554894785b:
#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;
}
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 BigInt::operator!()
{
if(size != 1)
return false;
return 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");
}