Now with GNU MultiPrecision (GMP) integers
authorSam Moore <[email protected]>
Mon, 7 Jul 2014 08:19:50 +0000 (16:19 +0800)
committerSam Moore <[email protected]>
Mon, 7 Jul 2014 08:19:50 +0000 (16:19 +0800)
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
src/arbint.cpp
src/gmpint.h [new file with mode: 0644]
src/main.cpp
src/tests/arbint_vs_gmpint.cpp [new file with mode: 0644]
src/tests/asm.cpp [deleted file]
src/tests/realops.cpp

index ec8789a..64408ed 100644 (file)
@@ -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'
index df6da8d..8af84f9 100644 (file)
@@ -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 (file)
index 0000000..11b53c5
--- /dev/null
@@ -0,0 +1,66 @@
+/**
+ * @file gmpint.h
+ * @brief Wraps to GMP mpz_t type using inlines
+ */
+
+#ifndef _GMPINT_H
+#define _GMPINT_H
+
+#include <gmp.h>
+#include <string>
+
+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
index 91e362c..79d8208 100644 (file)
@@ -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 (file)
index 0000000..2393d3a
--- /dev/null
@@ -0,0 +1,37 @@
+#include <gmp.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#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 (file)
index aa17b3b..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-#include <cstdlib>
-#include <cstdio>
-#include <iostream>
-
-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);
-       
-}
index 83a5241..b9ce441 100644 (file)
@@ -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);
 }

UCC git Repository :: git.ucc.asn.au