From 8c88a35a1fb0dfc9e542bb1a1c13c5f3e36eb3e5 Mon Sep 17 00:00:00 2001 From: Sam Moore Date: Mon, 7 Jul 2014 16:19:50 +0800 Subject: [PATCH] Now with GNU MultiPrecision (GMP) integers gmpint.h is (in theory) mostly inline and shouldn't add much overhead and was simpler than trying to understand the C++ "binding". The Str() function is kind of terrible but that can't be helped. Also fixed bug in realops tester (even the testers have bugs...) And removed asm tester because the asm function is gone. The bezier testers now don't compile, I don't think we need them anymore. --- src/Makefile | 4 +-- src/arbint.cpp | 11 +++++- src/gmpint.h | 66 ++++++++++++++++++++++++++++++++++ src/main.cpp | 2 +- src/tests/arbint_vs_gmpint.cpp | 37 +++++++++++++++++++ src/tests/asm.cpp | 17 --------- src/tests/realops.cpp | 2 +- 7 files changed, 117 insertions(+), 22 deletions(-) create mode 100644 src/gmpint.h create mode 100644 src/tests/arbint_vs_gmpint.cpp delete mode 100644 src/tests/asm.cpp 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..11b53c5 --- /dev/null +++ b/src/gmpint.h @@ -0,0 +1,66 @@ +/** + * @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() {return mpz_get_si(m_op);} + operator uint64_t() {return mpz_get_ui(m_op);} + operator double() {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/main.cpp b/src/main.cpp index 91e362c..79d8208 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -97,7 +97,7 @@ int main(int argc, char ** argv) //doc.Add(BEZIER, Rect(0.2+x-4.0, 0.2+y-4.0, 0.6,0.6), (x^y)%3); } } - doc.Add(BEZIER, Rect(0.1,0.1,0.8,0.8), 0); + doc.Add(CIRCLE_FILLED, Rect(0.1,0.1,0.8,0.8), 0); } Debug("Start!"); Rect bounds(b[0],b[1],b[2],b[3]); diff --git a/src/tests/arbint_vs_gmpint.cpp b/src/tests/arbint_vs_gmpint.cpp new file mode 100644 index 0000000..2393d3a --- /dev/null +++ b/src/tests/arbint_vs_gmpint.cpp @@ -0,0 +1,37 @@ +#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; + + Debug("Arbint - %s", arb_a.Str().c_str()); + Debug("Gmpint - %s", gmp_a.Str().c_str()); + } + + + } + 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); } -- 2.20.1