Keeping it Real, add Gmprat::Str, Gmprat::Log10
authorSam Moore <matches@ucc.asn.au>
Fri, 3 Oct 2014 06:25:06 +0000 (14:25 +0800)
committerSam Moore <matches@ucc.asn.au>
Fri, 3 Oct 2014 06:25:06 +0000 (14:25 +0800)
Fixed* all those horrible compile errors.
View can now use VReal and Path can now use PReal
and at the moment they are Gmprat unless the quadtree is enabled.

For Gmprat::Log10 there are problems.

Using: log(a/b) = log(a) - log(b)
       log(a*b) = log(a) + log(b)

Unfortunately mpz_div_ui quickly becomes a massive performance issue.
Even when well within the range of IEEE singles.

Need to rewrite Gmprat::Log10 but may as well commit since it works* slowly at least.

src/gmprat.h
src/graphicsbuffer.cpp
src/real.h
src/rect.h
src/view.cpp
src/view.h

index e0472ca..6782734 100644 (file)
@@ -20,18 +20,67 @@ class Gmprat
                
                //operator int64_t() const {return mpq_get_si(m_op);}
                //operator uint64_t() const {return mpq_get_ui(m_op);}
-               //operator double() const {return mpq_get_d(m_op);}
+               operator double() const {return mpq_get_d(m_op);}
                //operator float() const {return (float)ToDouble();}
                double ToDouble() const {return mpq_get_d(m_op);}
-               std::string Str(int base = 10) const
+               std::string Str() const
                {
                        //TODO: Make less hacky, if we care.
-                       char * buff = mpq_get_str(NULL, 10, m_op);
-                       std::string result(buff);
-                       free(buff);
-                       return result;
+                       // Convert to scientific notation
+                       if (Negative())
+                       {
+                               return "-" + operator-().Str();
+                       }
+                       double p = Log10();
+                       if (isinf(p))
+                               return "0";
+                               
+                       int P = (int)p;
+                       double C = pow(10.0, p - P);
+                       std::stringstream s;
+                       s << C;
+                       if (P != 0)
+                               s << "e"<< P;
+                       //s << "("<<ToDouble()<<")";
+                       return s.str();
                }
                
+               double Log10() const
+               {
+                       mpz_t num; mpz_init(num); mpq_get_num(num, m_op);
+                       mpz_t den; mpz_init(den); mpq_get_den(den, m_op);
+                       
+                       double lognum = 0;
+                       double logden = 0;
+                       while (mpz_sizeinbase(num, 10) > 10)
+                       {
+
+                               mpz_div_ui(num, num, 1e10);
+                               lognum += 10;
+                       }
+                       uint64_t n = mpz_get_ui(num);
+                       if (n == 0)
+                       {
+                               return -INFINITY;
+                       }
+                       lognum += log(n)/log(10.0);
+                       //Debug("%lu", mpz_get_ui(den));
+                       while (mpz_sizeinbase(den, 10) > 10)
+                       {
+                               mpz_div_ui(den, den, 1e10);
+                               logden += 10;
+                       }
+                       uint64_t d = mpz_get_ui(den);
+                       // if d is zero, its been rounded down we hope
+                       if (d != 0)
+                               logden += log(d)/log(10.0);
+                       
+                       return (lognum - logden);
+               }
+               
+
+               bool Negative() const {return (mpz_sgn(mpq_numref(m_op)) < 0);}
+               
                Gmprat & operator=(const Gmprat & equ) {mpq_set(m_op, equ.m_op); return *this;}
                Gmprat & operator=(const double & equ) {mpq_set_d(m_op, equ); return *this;}
                Gmprat & operator+=(const Gmprat & add) {mpq_add(m_op, m_op, add.m_op); return *this;}
@@ -62,7 +111,7 @@ class Gmprat
                mpq_t m_op;
 };     
 
-std::ostream & operator<<(std::ostream & os, const Gmprat & fith)
+inline std::ostream & operator<<(std::ostream & os, const Gmprat & fith)
 {
        os << fith.Str();
        return os;
index 8075453..844dfe8 100644 (file)
@@ -243,7 +243,7 @@ void GraphicsBuffer::UploadRange(size_t length, intptr_t offset, const void* dat
 
 void GraphicsBuffer::Resize(size_t length)
 {
-       if (m_invalidated && m_buffer_size > length)
+       if (m_invalidated && m_buffer_size >= length)
        {
                m_buffer_size = length;
        }
index 72def69..35b2c5e 100644 (file)
@@ -22,7 +22,7 @@
 
 #define XSTR(x) STR(x)
 #define STR(x) #x
-#pragma message "REALTYPE = " XSTR(REALTYPE)
+//#pragma message "REALTYPE = " XSTR(REALTYPE)
 
 #if REALTYPE == REAL_VFPU
        #include "vfpu.h"
index 25ef94e..0188446 100644 (file)
@@ -12,6 +12,7 @@ namespace IPDF
                T x; T y; T w; T h;
                //TRect() = default; // Needed so we can fread/fwrite this struct
                TRect(T _x=0, T _y=0, T _w=1, T _h=1) : x(_x), y(_y), w(_w), h(_h) {}
+               template <class B> TRect(const TRect<B> & cpy) : x(T(cpy.x)), y(T(cpy.y)), w(T(cpy.w)), h(T(cpy.h)) {}
                
                std::string Str() const
                {
@@ -38,7 +39,16 @@ namespace IPDF
                        return true;
                }
                
-               template <class B> TRect<B> Convert() {return TRect<B>(B(x), B(y), B(w), B(h));}
+               template <class B> TRect<B> Convert() const {return TRect<B>(B(x), B(y), B(w), B(h));}
+               
+               template <class B> TRect<T> & operator=(const TRect<B> & equ)
+               {
+                       x = T(equ.x);
+                       y = T(equ.y);
+                       w = T(equ.w);
+                       h = T(equ.h);
+                       return *this;
+               }
        };
 
 
index 0807643..53511d2 100644 (file)
@@ -84,7 +84,7 @@ View::~View()
  * Translate the view
  * @param x, y - Amount to translate
  */
-void View::Translate(VReal x, VReal y)
+void View::Translate(Real x, Real y)
 {
        if (!m_use_gpu_transform)
                m_buffer_dirty = true;
@@ -94,12 +94,10 @@ void View::Translate(VReal x, VReal y)
                #ifdef TRANSFORM_BEZIERS_TO_PATH
                        type = PATH;
                #endif
-       m_document.TranslateObjects(-x.ToDouble(), -y.ToDouble(), type);
+       m_document.TranslateObjects(-x, -y, type);
        #endif
-       x *= m_bounds.w;
-       y *= m_bounds.h;
-       m_bounds.x += x;
-       m_bounds.y += y;
+       m_bounds.x += m_bounds.w*VReal(x);
+       m_bounds.y += m_bounds.h*VReal(y);
        //Debug("View Bounds => %s", m_bounds.Str().c_str());
 
        
@@ -125,7 +123,7 @@ void View::SetBounds(const Rect & bounds)
  * @param x, y - Coordinates to scale at (eg: Mouse cursor position)
  * @param scale_amount - Amount to scale by
  */
-void View::ScaleAroundPoint(VReal x, VReal y, VReal scale_amount)
+void View::ScaleAroundPoint(Real x, Real y, Real scale_amount)
 {
        
        // (x0, y0, w, h) -> (x*w - (x*w - x0)*s, y*h - (y*h - y0)*s, w*s, h*s)
@@ -143,19 +141,19 @@ void View::ScaleAroundPoint(VReal x, VReal y, VReal scale_amount)
        #endif
        m_document.ScaleObjectsAboutPoint(x, y, scale_amount, type);
        #endif
-       x *= m_bounds.w;
-       y *= m_bounds.h;
-       x += m_bounds.x;
-       y += m_bounds.y;
+       VReal vx = m_bounds.w * VReal(x);
+       VReal vy = m_bounds.h * VReal(y);
+       vx += m_bounds.x;
+       vy += m_bounds.y;
        
-       VReal top = y - m_bounds.y;
-       VReal left = x - m_bounds.x;
+       VReal top = vy - m_bounds.y;
+       VReal left = vx - m_bounds.x;
        
        top *= scale_amount;
        left *= scale_amount;
        
-       m_bounds.x = x - left;
-       m_bounds.y = y - top;
+       m_bounds.x = vx - left;
+       m_bounds.y = vy - top;
        m_bounds.w *= scale_amount;
        m_bounds.h *= scale_amount;
        //Debug("Scale at {%s, %s} by %s View Bounds => %s", x.Str().c_str(), y.Str().c_str(), scale_amount.Str().c_str(), m_bounds.Str().c_str());
@@ -174,7 +172,7 @@ Rect View::TransformToViewCoords(const Rect& inp) const
        #ifdef TRANSFORM_OBJECTS_NOT_VIEW
                return inp;
        #endif
-       return TransformRectCoordinates(m_bounds, inp);
+       return TransformRectCoordinates(m_bounds.Convert<Real>(), inp);
 }
 
 /**
index 47eb0fb..1cb2221 100644 (file)
@@ -39,8 +39,8 @@ namespace IPDF
 
                        void Render(int width = 0, int height = 0);
                        
-                       void Translate(VReal x, VReal y);
-                       void ScaleAroundPoint(VReal x, VReal y, VReal scale_amount);
+                       void Translate(Real x, Real y);
+                       void ScaleAroundPoint(Real x, Real y, Real scale_amount);
                        void SetBounds(const Rect & new_bounds);
                        
                        Rect TransformToViewCoords(const Rect& inp) const;

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