473,396 Members | 2,082 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,396 software developers and data experts.

Diggins PDP #3 : arbitrary precision integers

// big_int.hpp
// The Diggins PDP (Public Domain Post) #3
// Public Domain code by Christopher Diggins, May 22, 2005
//
// Description:
// A naively implemented unsigned integer type for arbitrarily large
// values. Implemented using vector<bool>

#ifndef BIG_INT_HPP
#define BIG_INT_HPP

#include <limits>
#include <vector>
#include <algorithm>
#include <functional>
#include <stdexcept>
#include <cassert>
#include <iostream>
#include "binary_arithmetic.hpp" // Diggins PDP #1.2

#include <cassert>

namespace cdiggins
{
class big_int_impl
{
typedef big_int_impl self;
public:
self() {
}
self(const big_int_impl& x) : bits(x.bits) {
}
self(const std::vector<bool>& x) : bits(x) {
bits = x;
}
self(int x) {
while (x) {
bits.push_back(x & 0x1);
x >>= 1;
}
}
self& operator=(const std::vector<bool>& x) {
bits = x;
return *this;
}
self& operator<<=(int n) {
if (n == 0) return *this;
resize(size() + n);
for (int i=size() - 1; i >= n; i--) {
bits[i] = bits[i - n];
}
for (int i=n-1; i >= 0; i--) {
bits[i] = false;
}
truncate_leading_zeros();
return *this;
}
self& operator>>=(int n) {
if (n == 0) return *this;
if (n >= size()) return *this = 0;
for (int i=0; i < size() - n; i++) {
bits[i] = bits[i + n];
}
resize(size() - n);
return *this;
}
self operator++(int) {
self i = *this;
operator+=(1);
return i;
}
self operator--(int) {
self i = *this;
operator-=(1);
return i;
}
self& operator++() {
operator+=(1);
return *this;
}
self& operator--() {
operator-=(1);
return *this;
}
self& operator+=(const self& x) {
bool carry = false;
if (x.size() > size()) resize(x.size());
for (int i = 0; i < size(); i++) {
bits[i] = full_adder(bits[i], x[i], carry);
}
if (carry) {
resize(size() + 1);
bits[size() - 1] = 1;
}
truncate_leading_zeros();
return *this;
}
self& operator-=(const self& x) {
assert(x <= *this);
if (x == 0) return *this;
bool borrow = false;
for (int i = 0; i < size(); i++) {
bits[i] = full_subtractor(bits[i], x[i], borrow);
}
assert(!borrow); // should be no borrowing
truncate_leading_zeros();
return *this;
}
self& operator*=(self x) {
std::vector<bool> v = bits;
*this = 0;
for (int i=0; i < static_cast<int>(v.size()); i++)
{
if (v[i]) {
*this += x;
}
x <<= 1;
}
return *this;
}
self& operator/=(const self& x) {
return *this = divide_quotient(*this, x);
}
self& operator%=(const self& x) {
return *this = divide_remainder(*this, x);
}
self operator~() const {
std::vector<bool> v = bits;
for (int i=0; i<static_cast<int>(v.size()); i++) {
v[i] = !v[i];
}
return v;
}
self& operator&=(self x) {
if (x.size() > size()) {
resize(x.size());
}
if (x.size() < size()) {
x.resize(size());
}
std::transform(bits.begin(), bits.end(), x.bits.begin(), bits.begin(),
std::logical_and<bool>());
truncate_leading_zeros();
return *this;
}
self& operator|=(self x) {
if (x.size() > size()) {
resize(x.size());
}
if (x.size() < size()) {
x.resize(size());
}
std::transform(bits.begin(), bits.end(), x.bits.begin(), bits.begin(),
std::logical_or<bool>());
truncate_leading_zeros();
return *this;
}
self& operator^=(self x) {
if (x.size() > size()) {
resize(x.size());
}
if (x.size() < size()) {
x.resize(size());
}
std::transform(bits.begin(), bits.end(), x.bits.begin(), bits.begin(),
&logical_xor<bool>);
truncate_leading_zeros();
return *this;
}
bool operator[](int n) const {
if (n >= size()) return false;
return bits[n];
}
int size() const {
return static_cast<int>(bits.size());
}
unsigned long to_ulong() {
int digits = std::numeric_limits<unsigned long>::digits;
if (size() >= digits) {
throw std::domain_error("out of range for unsigned long");
}
unsigned long ret = 0;
unsigned long tmp = 1;
for (int i=0; i < digits; i++) {
if (operator[](i)) {
ret |= tmp;
}
tmp <<= 1;
}
return ret;
}
// friend functions
friend self operator<<(const self& x, unsigned int n) {
return self(x) <<= n;
}
friend self operator>>(const self& x, unsigned int n) {
return self(x) >>= n;
}
friend self operator+(const self& x, const self& y) {
return self(x) += y;
}
friend self operator-(const self& x, const self& y) {
return self(x) -= y;
}
friend self operator*(const self& x, const self& y) {
return self(x) *= y;
}
friend self operator/(const self& x, const self& y) {
return self(x) /= y;
}
friend self operator%(const self& x, const self& y) {
return self(x) %= y;
}
friend self operator^(const self& x, const self& y) {
return self(x) ^= y;
}
friend self operator&(const self& x, const self& y) {
return self(x) &= y;
}
friend self operator|(const self& x, const self& y) {
return self(x) |= y;
}
// comparison operators
friend bool operator==(const self& x, const self& y) {
if (x.size() != y.size()) return false;
for (int i=0; i < x.size(); i++) {
if (x[i] != y[i]) {
return false;
}
}
return true;
}
friend bool operator!=(const self& x, const self& y) {
return !(x == y);
}
friend bool operator>(const self& x, const self& y) {
int i = x.size();
if (i > y.size()) return true;
if (i < y.size()) return false;
while (i--) {
if (x[i] > y[i]) return true;
if (x[i] < y[i]) return false;
}
return false;
}
friend bool operator<(const self& x, const self& y) {
int i = x.size();
if (i > y.size()) return false;
if (i < y.size()) return true;
while (i--) {
if (x[i] > y[i]) return false;
if (x[i] < y[i]) return true;
}
return false;
}
friend bool operator>=(const self& x, const self& y) {
return (x > y) || (x == y);
}
friend bool operator<=(const self& x, const self& y) {
return (x < y) || (x == y);
}
private:
void resize(int n) {
int old = size();
bits.resize(n);
for (int i=old; i < n; i++) {
bits[i] = false;
}
}
void truncate_leading_zeros() {
int sig_digit = -1;
for (int i=0; i<size(); i++) {
if (bits[i]) {
sig_digit = static_cast<int>(i);
}
}
resize(sig_digit + 1);
}
std::vector<bool> bits;
};

typedef big_int_impl big_int;
}

///////////////////////////////////////////////////
// test code

#include <iostream>
#include <iterator>

void test_failure(const char* x) {
std::cerr << "TEST failed " << x << std::endl;
}
#define TEST(TKN) if (!(TKN)) { test_failure(#TKN); } /* */

namespace big_int_test
{
using namespace cdiggins;

std::ostream& operator<<(std::ostream& o, big_int x)
{
std::vector<int> v;
if (x == 0) {
o << 0;
return o;
}
while (x > 0) {
v.push_back((x % 10).to_ulong());
x /= 10;
}
std::copy(v.rbegin(), v.rend(), std::ostream_iterator<int>(o));
return o;
}

// makes a big int as a power of base to the power
big_int make_big_int(int base, int power) {
big_int ret = 1;
for (int i=0; i < power; i++) {
ret *= base;
}
return ret;
}

void simple_test(big_int n)
{
big_int original = n;
std::cout << n << std::endl;

TEST(n == n);
TEST(n >= n);
TEST(n <= n);
TEST(!(n < n));
TEST(!(n > n));
TEST(n != 0);
TEST(!(n == 0));
TEST(n > 0);
TEST(n >= 0);
TEST(!(n < 0));
TEST(!(n <= 0));

TEST((n >> 1) <= n);
TEST((n << 1) >= n);

TEST(0 + n == n);
TEST(n + 0 == n);
TEST(n - 0 == n);
TEST(n - n == 0);
TEST(n * 1 == n);
TEST(n * 0 == 0);
TEST(n / 1 == n);
TEST(n / n == 1);
TEST(n % n == 0);
TEST(n % 1 == 0);

TEST((n += 0) == n);
TEST(n == original);
TEST((n -= 0) == n);
TEST(n == original);
TEST((n *= 1) == n);
TEST(n == original);
TEST((n /= 1) == n);
TEST(n == original);

TEST(n != n + 1);
TEST(n < n + 1);
TEST(n < n * 2);
TEST(n <= n * n);
TEST(n != (n - 1));
TEST(n > (n - 1));
TEST(n == original);

TEST((n & 1) == n[0]);
TEST((n & 1) == n % 2);
TEST((n & ~n) == 0);
TEST((n | n) == n);
TEST(((n ^ n) ^ n) == n);
TEST(n == original);

TEST(n * 2 == n << 1);
TEST(n * 2 == n + n);
TEST(n + n + n == n * 2 + n);
TEST(n + n + n == n * 3);
TEST(n / 2 == n >> 1);
TEST((n * 3) / 3 == n);
TEST(n == original);
TEST(n * 2 == n * 3 - n);
TEST(n == (n / 2) * 2 + (n % 2));
TEST(n == (n / 3) * 3 + (n % 3));
TEST(n == original);

big_int m = n;
for (int i=0; i<16; i++) {
TEST(m++ == n + i);
}
while (--m > n) { }

TEST(m == n);
TEST(m++ == n);
TEST(m == n + 1);
TEST(++m == n + 2);
TEST(m-- == n + 2);
TEST(--m == n);
TEST(m == n);
TEST(--m == n - 1);
TEST(n == original);
}

void test_main()
{
// check out all the small numbers
int i=1;
for (; i<64; i++) {
std::cout << "testing " << i << std::endl;
simple_test(i);
}
// check out some bigger numbers
for (; i<640; i += 13) {
std::cout << "testing " << i << std::endl;
simple_test(i);
}
// check out some even bigger numbers
for (; i<6400; i += 151) {
std::cout << "testing " << i << std::endl;
simple_test(i);
}
// check out various powers of two
for (int i=4; i < 64; i++) {
std::cout << "testing 2 raised to the power of " << i << std::endl;
simple_test(make_big_int(2, i));
}
// check out various powers of three
for (int i=2; i < 32; i++) {
std::cout << "testing 3 raised to the power of " << i << std::endl;
simple_test(make_big_int(3, i));
}
// check out various powers of five
for (int i=2; i < 20; i++) {
std::cout << "testing 5 raised to the power of " << i << std::endl;
simple_test(make_big_int(5, i));
}
// check out various powers of eleven
for (int i=2; i < 10; i++) {
std::cout << "testing 11 raised to the power of " << i << std::endl;
simple_test(make_big_int(11, i));
}
}
}

#endif

Jul 23 '05 #1
0 1056

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
by: Thinkit | last post by:
Are there any good libraries of arbitrary precision binary floats? I'd like to specify the mantissa length and exponent range. Hexadecimal output would be best (decimal is disgusting with binary...
0
by: Thinkit | last post by:
Are there any packages for arbitrary precision binary floats? Something along the lines of Gnu Multi Precision. I saw quite a few rationals classes, but not this. Just looking to be able to use...
2
by: cpptutor2000 | last post by:
Could some C++ guru please help me? I am using a BigInteger class which is really a wrapper around a C source file(mpi.c) that does arbitrary precision arithmetic operations. When I compile the C...
5
by: Mattias Brändström | last post by:
Hello! I am trying to find a minimal class/lib that handles arbitrary precision decimal numbers. I would be happy if this class supported as little as addition, subtraction, multiplication,...
4
by: christopher diggins | last post by:
Welcome to the first installment of the Diggins Public Domain Posts (PDP). There is a significant dearth of good public domain C++ code. All of it seems to come with one kind of a license or...
3
by: Jack | last post by:
Quick question, does anyone know what the limitations are, besides memory for GMP, and also, if I write software that uses this library, is it true that it may run differently on different hardware...
12
by: Chadwick Boggs | last post by:
I need to perform modulo operations on extremely large numbers. The % operator is giving me number out of range errors and the mod(x, y) function simply seems to return the wrong results. Also,...
8
by: Martin the Third | last post by:
Hi, I need some help! I'm writing an infinite-precision floating point library called ipfloat (I know infinite is a misnomer - but arbitrary was taken). A quick overview: I'm storing numbers as...
2
by: Rob Clewley | last post by:
Dear Pythonistas, How many times have we seen posts recently along the lines of "why is it that 0.1 appears as 0.10000000000000001 in python?" that lead to posters being sent to the definition...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.