[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
GMP C++ wrap
From: |
Hans Aberg |
Subject: |
GMP C++ wrap |
Date: |
Wed, 25 Apr 2001 13:56:31 +0200 |
At 08:13 +1000 2001/04/25, Kevin Ryde wrote:
>> I started on a C++ wrap, classes gmp::integer, gmp::rational, gmp::floating
>> that expand to the GMP C functions.
...
>Gerardo Ballabio has made good progress on such a wrapper,
>
> http://www.sissa.it/~ballabio/gmp++.html
I had a look at this
My style is quite different; but my objectives are quite different.
I decided with only one header <gmp>, and the classes are put in a
namespace gmp.
Below is a sample, the integer class (with example code). The style is similar:
gmp::integer x = ..., y = ..., z;
z = x * y;
etc.
-- File <gmp> --------------------------------------------------------------
#include <iostream>
#include <string>
#include "gmp.h"
#include "gmp-impl.h"
namespace gmp {
typedef int relate;
const relate unrelated = -2;
const relate less = -1;
const relate equal = 0;
const relate greater = 1;
template<class A> // The sign of a number:
inline int sgn(A x) { return (x > 0) - (x < 0); }
inline bool less_equal(relate r) { return r == less || r == equal; }
inline bool greater_equal(relate r) { return r == greater || r == equal; }
class rational;
class floating;
class integer {
public:
mpz_t value_;
public:
integer() { mpz_init(value_); }
~integer() { mpz_clear(value_); }
integer(const integer& x) { mpz_init_set(value_, x.value_); }
integer& operator=(const integer& x) { mpz_set(value_, x.value_); return
*this; }
integer(unsigned long int x) { mpz_init_set_ui(value_, x); }
integer(signed long int x) { mpz_init_set_si(value_, x); }
integer(double x) { mpz_init_set_d(value_, x); }
integer(const char* str, int base = 0) { mpz_init_set_str(value_, str,
base); }
// Make explicit functions, instaed of type conversions:
// integer(const rational& x) { mpz_init_set_q(value_, x); }
// integer(const floating& x) { mpz_init_set_f(value_, x); }
integer& operator=(unsigned long int x) { mpz_set_ui(value_, x); return
*this; }
integer& operator=(signed long int x) { mpz_set_si(value_, x); return
*this; }
integer& operator=(double x) { mpz_set_d(value_, x); return *this; }
integer& operator=(const char* str) { mpz_set_str(value_, str, 0); return
*this; }
integer& operator=(const rational& x); // { mpz_set_q(value_, x); }
integer& operator=(const floating& x); // { mpz_set_f(value_, x); }
double get_d() const { return mpz_get_d(value_); }
signed long int get_si() const { return mpz_get_si(value_); }
unsigned long int get_ui() const { return mpz_get_ui(value_); }
std::string str(int base = 10) const {
char* cs = new char[mpz_sizeinbase(value_, base) + 2];
mpz_get_str(cs, base, value_);
std::string str_r(cs); delete[] cs;
return str_r;
}
relate compare(const integer& x) const { return sgn(mpz_cmp(value_,
x.value_)); }
void swap(integer& x) { mpz_swap(value_, x.value_); }
size_t read(std::istream&, int base = 0);
friend integer operator+(const integer&, const integer&);
friend integer operator-(const integer&);
friend integer operator-(const integer&, const integer&);
friend integer operator*(const integer&, const integer&);
friend bool operator<(const integer&, const integer&);
friend bool operator<=(const integer&, const integer&);
friend bool operator==(const integer&, const integer&);
friend bool operator!=(const integer&, const integer&);
friend bool operator>(const integer&, const integer&);
friend bool operator>=(const integer&, const integer&);
friend integer abs(const integer&); // Absolute value.
friend std::istream& operator>>(std::istream&, integer&);
friend std::ostream& operator<<(std::ostream&, const integer&);
};
inline integer operator+(const integer& x, const integer& y) {
integer r; mpz_add(r.value_, x.value_, y.value_); return r;
}
inline integer operator-(const integer& x) {
integer r; mpz_neg(r.value_, x.value_); return r;
}
inline integer operator-(const integer& x, const integer& y) {
integer r; mpz_sub(r.value_, x.value_, y.value_); return r;
}
inline integer operator*(const integer& x, const integer& y) {
integer r; mpz_mul(r.value_, x.value_, y.value_); return r;
}
inline bool operator<(const integer& x, const integer& y)
{ return x.compare(y) == less; }
inline bool operator<=(const integer& x, const integer& y)
{ return less_equal(x.compare(y)); }
inline bool operator==(const integer& x, const integer& y)
{ return x.compare(y) == equal; }
inline bool operator!=(const integer& x, const integer& y)
{ return x.compare(y) != equal; }
inline bool operator>(const integer& x, const integer& y)
{ return x.compare(y) == greater; }
inline bool operator>=(const integer& x, const integer& y)
{ return greater_equal(x.compare(y)); }
inline integer abs(const integer& x) {
integer r; mpz_abs(r.value_, x.value_); return r;
}
inline std::istream& operator>>(std::istream& is, integer& x) {
x.read(is); return is;
}
inline std::ostream& operator<<(std::ostream& os, const integer& n) {
return os << n.str();
}
} // namespace gmp
-- File <gmp.cc> --------------------------------------------------------------
#include <sstream>
namespace gmp {
// Class integer:
static int digit_value_in_base(int c, int base) {
int digit;
if (isdigit(c))
digit = c - '0';
else if (islower(c))
digit = c - 'a' + 10;
else if (isupper(c))
digit = c - 'A' + 10;
else
return -1;
if (digit < base)
return digit;
return -1;
}
size_t integer::read(std::istream& stream, int base)
{
mpz_ptr x = value_;
char *str;
size_t alloc_size, str_size;
int c;
int negative;
mp_size_t xsize;
size_t nread;
nread = 0;
/* Skip whitespace. */
do
{
c = stream.get();
nread++;
}
while (isspace(c));
negative = 0;
if (c == '-')
{
negative = 1;
c = stream.get();
nread++;
}
if (digit_value_in_base (c, base == 0 ? 10 : base) < 0)
return 0; /* error if no digits */
/* If BASE is 0, try to find out the base by looking at the initial
characters. */
if (base == 0)
{
base = 10;
if (c == '0')
{
base = 8;
c = stream.get();
nread++;
if (c == 'x' || c == 'X')
{
base = 16;
c = stream.get();
nread++;
}
else if (c == 'b' || c == 'B')
{
base = 2;
c = stream.get();
nread++;
}
}
}
/* Skip leading zeros. */
while (c == '0')
{
c = stream.get();
nread++;
}
alloc_size = 100;
str = (char *) (*_mp_allocate_func) (alloc_size);
str_size = 0;
for (;;)
{
int dig;
if (str_size >= alloc_size)
{
size_t old_alloc_size = alloc_size;
alloc_size = alloc_size * 3 / 2;
str = (char *) (*_mp_reallocate_func) (str, old_alloc_size, alloc_size);
}
dig = digit_value_in_base (c, base);
if (dig < 0)
break;
str[str_size++] = dig;
c = stream.get();
}
stream.unget();
/* Make sure the string is not empty, mpn_set_str would fail. */
if (str_size == 0)
{
x->_mp_size = 0;
(*_mp_free_func) (str, alloc_size);
return nread;
}
xsize = (((mp_size_t) (str_size / __mp_bases[base].chars_per_bit_exactly))
/ BITS_PER_MP_LIMB + 2);
if (x->_mp_alloc < xsize)
_mpz_realloc (x, xsize);
/* Convert the byte array in base BASE to our bignum format. */
xsize = mpn_set_str (x->_mp_d, (unsigned char *) str, str_size, base);
x->_mp_size = negative ? -xsize : xsize;
(*_mp_free_func) (str, alloc_size);
return str_size + nread;
}
} // namespace gmp
--- File main.cc -----------------------------------------------------------
#include <iostream>
#include "gmp"
#define show_bool(x) (x? "true" : "false")
int main() {
gmp::integer x, y;
for (;;) {
std::cout << "x = " << std::flush;
if (!(std::cin >> x)) continue;
if (x == -1L) break;
std::cout << "y = " << std::flush;
if (!(std::cin >> y)) continue;
std::cout << " x = " << x << std::endl;
std::cout << " y = " << y << std::endl;
std::cout << " -x = " << -x << std::endl;
std::cout << "x + y = " << x + y << std::endl;
std::cout << "x - y = " << x - y << std::endl;
std::cout << "x * y = " << x * y << std::endl;
std::cout << " x < y = " << show_bool(x < y) << std::endl;
std::cout << "x <= y = " << show_bool(x <= y) << std::endl;
std::cout << "x == y = " << show_bool(x == y) << std::endl;
std::cout << "x != y = " << show_bool(x != y) << std::endl;
std::cout << " x > y = " << show_bool(x > y) << std::endl;
std::cout << "x >= y = " << show_bool(x >= y) << std::endl;
}
std::cout << "Bye, bye!" << std::endl;
return 0;
}
-----------------------------------------------------------------
Hans Aberg
- GMP MacOS PPC assembler, (continued)
- GMP MacOS PPC assembler, Hans Aberg, 2001/04/26
- Re: GMP MacOS PPC assembler, Linus Nordberg, 2001/04/26
- Re: GMP MacOS PPC assembler, Hans Aberg, 2001/04/26
- Re: GMP MacOS PPC assembler, Torbjorn Granlund, 2001/04/27
- Re: GMP MacOS PPC assembler, Hans Aberg, 2001/04/27
- Re: GMP MacOS PPC assembler, Kevin Ryde, 2001/04/29
- Re: GMP MacOS PPC assembler, Hans Aberg, 2001/04/30
- GMP parser, Hans Aberg, 2001/04/26
- Re: GMP parser, Kevin Ryde, 2001/04/29
- Re: GMP parser, Hans Aberg, 2001/04/30
- GMP C++ wrap,
Hans Aberg <=
- GMP Inputs, Hans Aberg, 2001/04/25
- Re: GMP Inputs, Kevin Ryde, 2001/04/25
- Re: GMP Inputs, Hans Aberg, 2001/04/26
GMP ceil/floor/trunc, Hans Aberg, 2001/04/24