From: David Gow Date: Mon, 7 Jul 2014 16:02:11 +0000 (+0800) Subject: Merge branch 'master' of git.ucc.asn.au:ipdf/code X-Git-Url: https://git.ucc.asn.au/?p=ipdf%2Fcode.git;a=commitdiff_plain;h=85e08223a33439f9b4911129b48ee45ff65869eb;hp=2db1211c9a24a0cd22da1d3ddcddf564f814fc0a Merge branch 'master' of git.ucc.asn.au:ipdf/code --- diff --git a/src/Makefile b/src/Makefile index ec8789a..64408ed 100644 --- a/src/Makefile +++ b/src/Makefile @@ -4,8 +4,8 @@ ARCH := $(shell uname -m) CXX = g++ -std=gnu++0x -g -Wall -Werror -Wshadow -pedantic -rdynamic MAIN = main.o OBJ = log.o real.o bezier.o document.o objectrenderer.o view.o screen.o vfpu.o graphicsbuffer.o framebuffer.o shaderprogram.o stb_truetype.o gl_core44.o add_digits_asm.o sub_digits_asm.o mul_digits_asm.o div_digits_asm.o arbint.o -LIB_x86_64 = ../contrib/lib/libSDL2-2.0.so.0 -lGL -LIB_i386 = ../contrib/lib32/libSDL2-2.0.so.0 -lGL +LIB_x86_64 = ../contrib/lib/libSDL2-2.0.so.0 -lGL -lgmp +LIB_i386 = ../contrib/lib32/libSDL2-2.0.so.0 -lGL -lgmp MAINRPATH_x86_64 = -Wl,-rpath,'$$ORIGIN/../contrib/lib' MAINRPATH_i386 = -Wl,-rpath,'$$ORIGIN/../contrib/lib32' diff --git a/src/arbint.cpp b/src/arbint.cpp index df6da8d..8af84f9 100644 --- a/src/arbint.cpp +++ b/src/arbint.cpp @@ -271,7 +271,16 @@ string Arbint::Str(const string & base) const { string s(""); Arbint cpy(*this); - + unsigned b = base.size(); + while (cpy > Arbint(0L)) + { + //Debug("cpy is %s", cpy.DigitStr().c_str()); + unsigned c = (unsigned)(cpy % Arbint(b)).AsDigit(); + s += base[c]; + cpy /= Arbint(b); + } + if (m_sign) + s += '-'; reverse(s.begin(), s.end()); return s; } diff --git a/src/gmpint.h b/src/gmpint.h new file mode 100644 index 0000000..4f45231 --- /dev/null +++ b/src/gmpint.h @@ -0,0 +1,65 @@ +/** + * @file gmpint.h + * @brief Wraps to GMP mpz_t type using inlines + */ + +#ifndef _GMPINT_H +#define _GMPINT_H + +#include +#include + +class Gmpint +{ + public: + Gmpint(int64_t i) {mpz_init_set_si(m_op, i);} + Gmpint(const std::string & str, int base=10) {mpz_init_set_str(m_op, str.c_str(), base);} + Gmpint(const Gmpint & cpy) {mpz_init(m_op); mpz_set(m_op, cpy.m_op);} + virtual ~Gmpint() {} //TODO: Do we need to delete m_op somehow? + + + operator int64_t() const {return mpz_get_si(m_op);} + operator uint64_t() const {return mpz_get_ui(m_op);} + operator double() const {return mpz_get_d(m_op);} + std::string Str(int base = 10) const + { + //TODO: Make less hacky, if we care. + char * buff = mpz_get_str(NULL, 10, m_op); + std::string result(buff); + free(buff); + return result; + } + + Gmpint & operator=(const Gmpint & equ) {mpz_set(m_op, equ.m_op); return *this;} + Gmpint & operator+=(const Gmpint & add) {mpz_add(m_op, m_op, add.m_op); return *this;} + Gmpint & operator-=(const Gmpint & sub) {mpz_sub(m_op, m_op, sub.m_op); return *this;} + Gmpint & operator*=(const Gmpint & mul) {mpz_mul(m_op, m_op, mul.m_op); return *this;} + Gmpint & operator/=(const Gmpint & div) {mpz_div(m_op, m_op, div.m_op); return *this;} + + Gmpint operator+(const Gmpint & add) const {Gmpint a(*this); a += add; return a;} + Gmpint operator-(const Gmpint & sub) const {Gmpint a(*this); a -= sub; return a;} + Gmpint operator*(const Gmpint & mul) const {Gmpint a(*this); a *= mul; return a;} + Gmpint operator/(const Gmpint & div) const {Gmpint a(*this); a /= div; return a;} + Gmpint operator%(const Gmpint & div) const {Gmpint a(*this); mpz_mod(a.m_op, a.m_op, div.m_op); return a;} + Gmpint operator-() const {return (Gmpint(0L)-*this);} + + + bool operator==(const Gmpint & cmp) const {return mpz_cmp(m_op, cmp.m_op) == 0;} + bool operator!=(const Gmpint & cmp) const {return mpz_cmp(m_op, cmp.m_op) != 0;} + bool operator<(const Gmpint & cmp) const {return mpz_cmp(m_op, cmp.m_op) < 0;} + bool operator>(const Gmpint & cmp) const {return mpz_cmp(m_op, cmp.m_op) > 0;} + bool operator<=(const Gmpint & cmp) const {return mpz_cmp(m_op, cmp.m_op) <= 0;} + bool operator>=(const Gmpint & cmp) const {return mpz_cmp(m_op, cmp.m_op) >= 0;} + + Gmpint Abs() const {Gmpint a(*this); mpz_abs(a.m_op, a.m_op); return a;} + + + private: + Gmpint(const mpz_t & op) : m_op(op) {} + mpz_t m_op; +}; + + + + +#endif //_GMPINT_H diff --git a/src/rational.h b/src/rational.h index 61a38ab..6bc5aec 100644 --- a/src/rational.h +++ b/src/rational.h @@ -9,6 +9,7 @@ #include #include #include "arbint.h" +#include "gmpint.h" namespace IPDF { @@ -18,7 +19,7 @@ template T Tabs(const T & a) return abs(a); } template <> Arbint Tabs(const Arbint & a); - +template <> Gmpint Tabs(const Gmpint & a); /* Recursive version of GCD template diff --git a/src/real.cpp b/src/real.cpp index 83b3fb8..ce2f976 100644 --- a/src/real.cpp +++ b/src/real.cpp @@ -11,5 +11,10 @@ namespace IPDF "Rational", "Rational" }; + + template <> Gmpint Tabs(const Gmpint & a) + { + return a.Abs(); + } } diff --git a/src/real.h b/src/real.h index 8dea953..798ea0b 100644 --- a/src/real.h +++ b/src/real.h @@ -26,6 +26,7 @@ #if REAL == REAL_RATIONAL_ARBINT #include "rational.h" #include "arbint.h" + #include "gmpint.h" #endif //REAL namespace IPDF @@ -48,14 +49,16 @@ namespace IPDF inline float Float(const Real & r) {return (float)r.ToDouble();} inline double Double(const Real & r) {return r.ToDouble();} #elif REAL == REAL_RATIONAL_ARBINT - typedef Rational Real; + #define ARBINT Gmpint // Set to Gmpint or Arbint here + + typedef Rational Real; inline float Float(const Real & r) {return (float)r.ToDouble();} inline double Double(const Real & r) {return r.ToDouble();} - inline Rational pow(const Rational & a, const Rational & b) + inline Rational pow(const Rational & a, const Rational & b) { - Arbint P(std::pow(static_cast(a.P), b.ToDouble())); - Arbint Q(std::pow(static_cast(a.Q), b.ToDouble())); - return Rational(P,Q); + ARBINT P(std::pow(static_cast(a.P), b.ToDouble())); + ARBINT Q(std::pow(static_cast(a.Q), b.ToDouble())); + return Rational(P,Q); } #else #error "Type of Real unspecified." diff --git a/src/tests/arbint_vs_gmpint.cpp b/src/tests/arbint_vs_gmpint.cpp new file mode 100644 index 0000000..306bbb7 --- /dev/null +++ b/src/tests/arbint_vs_gmpint.cpp @@ -0,0 +1,40 @@ +#include +#include +#include + +#include "log.h" + +#include "gmpint.h" +#include "arbint.h" + +#define TEST_CASES 100 + +using namespace IPDF; + +int main(int argc, char ** argv) +{ + for (unsigned i = 0; i < TEST_CASES; ++i) + { + uint64_t a = rand(); + + Arbint arb_a(a); + Gmpint gmp_a(a); + + uint64_t b = rand(); + + for (unsigned j = 0; j < 5; ++j) + { + arb_a *= b; + gmp_a *= b; + } + + for (unsigned j = 0; j < 5; ++j) + { + arb_a /= b; + gmp_a /= b; + } + + + } + return 0; +} diff --git a/src/tests/asm.cpp b/src/tests/asm.cpp deleted file mode 100644 index aa17b3b..0000000 --- a/src/tests/asm.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include -#include -#include - -using namespace std; - - - -int main(int argc, char ** argv) -{ - uint32_t a = 4294967295; - uint32_t b = 0; - uint32_t r = 0; - bool c = addc(a, b, &r); - printf("%u + %u = %u (%u)\n", a, b, r, (uint32_t)c); - -} diff --git a/src/tests/realops.cpp b/src/tests/realops.cpp index 83a5241..b9ce441 100644 --- a/src/tests/realops.cpp +++ b/src/tests/realops.cpp @@ -10,7 +10,7 @@ static double g_totalerror = 0; bool NotEqual(double a, double b, double threshold=1e-1) { - double error = (fabs(a-b) > threshold); + double error = fabs(a-b); g_totalerror += error; return (error > threshold); }