It's slow but less slow than Rationals.
Project complete.
Haha I wish.
QT_DEF := -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB
QT_LIB := -L/usr/lib/x86_64-linux-gnu -lQtGui -lQtCore -lpthread
-LIB_x86_64 = ../contrib/lib/libSDL2-2.0.so.0 -lGL -lgmp $(QT_LIB)
+LIB_x86_64 = ../contrib/lib/libSDL2-2.0.so.0 -lGL -lmpfr -lgmp $(QT_LIB)
LIB_i386 = ../contrib/lib32/libSDL2-2.0.so.0 -lGL -lgmp
LIB_i686 = $(LIB_i386)
{
Real ptx, pty;
Evaluate(ptx, pty, t);
- Debug("Root: t = %f, (%f,%f)", t, ptx, pty);
+ Debug("Root: t = %f, (%f,%f)", Double(t), Double(ptx), Double(pty));
}
std::vector<Bezier> all_beziers;
unsigned data_index = AddPathData(path);
Rect bounds = path.SolveBounds(m_objects);
unsigned result = Add(PATH, bounds,data_index);
+ //Debug("Added path %u -> %u (%u objects) colour {%u,%u,%u,%u}, stroke {%u,%u,%u,%u}", start_index, end_index, (end_index - start_index), fill.r, fill.g, fill.b, fill.a, stroke.r, stroke.g, stroke.b, stroke.a);
return result;
}
{
AddPath(start_index, end_index);
}
- Debug("Added Glyph \"%c\" at %f %f, scale %f", (char)character, Float(x), Float(y), Float(scale));
+ //Debug("Added Glyph \"%c\" at %f %f, scale %f", (char)character, Float(x), Float(y), Float(scale));
stbtt_FreeShape(font, instructions);
}
}
// It is the only way.
+// Dear god what have I done
void RatCatcher(int x, int y, int buttons, int wheel, Screen * scr, View * view)
{
static bool oldButtonDown = false;
}
if (buttons)
{
- #if REAL >= REAL_RATIONAL
+ #if REAL == REAL_RATIONAL
view->Translate(Real(oldx, scr->ViewportWidth()) -Real(x,scr->ViewportWidth()), Real(oldy, scr->ViewportHeight()) - Real(y,scr->ViewportHeight()));
#else
view->Translate(Real(oldx-x)/Real(scr->ViewportWidth()), Real(oldy-y)/Real(scr->ViewportHeight()));
if (wheel)
{
- #if REAL >= REAL_RATIONAL
+ #if REAL == REAL_RATIONAL
view->ScaleAroundPoint(Real(x,scr->ViewportWidth()), Real(y,scr->ViewportHeight()), Real(20-wheel, 20));
#else
view->ScaleAroundPoint(Real(x)/Real(scr->ViewportWidth()),Real(y)/Real(scr->ViewportHeight()), Real(expf(-wheel/20.f)));
Rect bounds(CPURenderBounds(objects.bounds[m_indexes[i]], view, target));
PixelBounds pix_bounds(bounds);
- const Path & path = objects.paths[objects.data_indices[m_indexes[i]]];
+ Path & path = objects.paths[objects.data_indices[m_indexes[i]]];
if (view.ShowingFillPoints())
{
if (pix_bounds.w*pix_bounds.h > 100)
{
+ vector<Vec2> & fill_points = path.FillPoints(objects, view);
Debug("High resolution; use fill points %u,%u", pix_bounds.w, pix_bounds.h);
- for (unsigned f = 0; f < path.m_fill_points.size(); ++f)
+ for (unsigned f = 0; f < fill_points.size(); ++f)
{
- PixelPoint fill_point(CPUPointLocation(path.m_fill_points[f], view, target));
+ PixelPoint fill_point(CPUPointLocation(fill_points[f], view, target));
FloodFillOnCPU(fill_point.first, fill_point.second, pix_bounds, target, path.m_fill, path.m_stroke);
}
#include <sstream>
#include <fenv.h>
#include "log.h"
+#include <iostream>
using namespace std;
namespace IPDF
{
-ParanoidNumber::ParanoidNumber(const char * str) : m_value(0), m_op(ADD), m_next(NULL)
+ParanoidNumber::ParanoidNumber(const char * str) : m_value(0), m_op(ADD), m_next_term(NULL), m_next_factor(NULL)
{
int dp = 0;
int end = 0;
{
ParanoidNumber b(str[i]-'0');
b*=m;
+ //Debug("m is %s", m.Str().c_str());
+ //Debug("Add %s", b.Str().c_str());
this->operator+=(b);
+ //Debug("Now at %s", Str().c_str());
m*=10;
}
ParanoidNumber n(1);
{
n/=10;
ParanoidNumber b(str[i]-'0');
+ //Debug("%s * %s", b.Str().c_str(), n.Str().c_str());
b*=n;
+ //Debug("b -> %s", b.Str().c_str());
+ //Debug("Add %s", b.Str().c_str());
this->operator+=(b);
- }
-
-}
+ //Debug("Now at %s", Str().c_str());
-ParanoidNumber * ParanoidNumber::InsertAfter(float value, Optype op)
-{
- return InsertAfter(new ParanoidNumber(value, op));
-}
-
-ParanoidNumber * ParanoidNumber::InsertAfter(ParanoidNumber * insert)
-{
- //Debug("Insert {%s} after {%f, %s}",insert->Str().c_str(),
- // m_value, g_opstr[m_op]);
- ParanoidNumber * n = m_next;
- m_next = insert;
-
- ParanoidNumber * p = m_next;
- while (p->m_next != NULL)
- p = p->m_next;
- p->m_next = n;
-
- return m_next;
+ }
+ Debug("Constructed {%s} from %s (%f)", Str().c_str(), str, ToDouble());
}
-
ParanoidNumber & ParanoidNumber::operator=(const ParanoidNumber & a)
{
- const ParanoidNumber * na = &a;
- ParanoidNumber * nb = this;
- ParanoidNumber * p = NULL;
- while (na != NULL && nb != NULL)
+ //TODO: Optimise
+ delete m_next_term;
+ delete m_next_factor;
+ m_op = a.m_op;
+ if (a.m_next_term != NULL)
{
- nb->m_value = na->m_value;
- nb->m_op = na->m_op;
- na = na->m_next;
- p = nb;
- nb = nb->m_next;
-
- }
-
- while (na != NULL) // => nb == NULL
- {
- InsertAfter(na->m_value, na->m_op);
- na = na->m_next;
+ m_next_term = new ParanoidNumber(*(a.m_next_term));
}
-
- if (nb != NULL)
+ if (a.m_next_factor != NULL)
{
- if (p != NULL)
- p->m_next = NULL;
- delete nb;
+ m_next_factor = new ParanoidNumber(*(a.m_next_factor));
}
return *this;
}
ParanoidNumber & ParanoidNumber::operator+=(const ParanoidNumber & a)
{
- ParanoidNumber * insert = new ParanoidNumber(a, ADD);
- if (m_next == NULL || m_next->m_op == ADD || m_next->m_op == SUBTRACT)
- {
- InsertAfter(insert);
- Simplify();
- return *this;
- }
+ // this = v + t + (a)
+ // -> v + (a) + t
- if (m_next->m_op == MULTIPLY) // (a*b) + c == (a+[c/b]) * b
- insert->operator/=(*m_next);
- else
- insert->operator*=(*m_next); // (a/b) + c == (a+[c*b])/b
+ ParanoidNumber * nt = m_next_term;
+ ParanoidNumber * nf = m_next_factor;
- if (insert->m_next != NULL) // neither of the above simplified
- {
- //Debug("{%s} did not simplify, change back to {%s}", insert->Str().c_str(), a.Str().c_str());
- insert->operator=(a); // Just add as is
- insert->m_op = ADD;
- ParanoidNumber * n = this;
- while (n->m_next != NULL)
- n = n->m_next;
- n->InsertAfter(insert);
- }
- else
+ ParanoidNumber ca(a);
+ if (m_next_factor != NULL)
{
- InsertAfter(insert);
+ if (m_next_factor->m_op == MULTIPLY)
+ ca /= (*m_next_factor);
+ else
+ ca *= (*m_next_factor);
+
+ if (ca.Floating())
+ {
+ m_next_factor = NULL;
+ m_next_term = NULL;
+ operator+=(ca);
+ m_next_factor = nf;
+ m_next_term = nt;
+ Simplify();
+ return *this;
+ }
+
}
+
+ m_next_term = new ParanoidNumber(a, ADD);
+ ParanoidNumber * t = m_next_term;
+ while (t->m_next_term != NULL)
+ t = t->m_next_term;
+ t->m_next_term = nt;
+ //Debug("Simplify {%s} after add", Str().c_str());
Simplify();
return *this;
}
+
ParanoidNumber & ParanoidNumber::operator-=(const ParanoidNumber & a)
{
- ParanoidNumber * insert = new ParanoidNumber(a, SUBTRACT);
- if (m_next == NULL || m_next->m_op == ADD || m_next->m_op == SUBTRACT)
- {
- InsertAfter(insert);
- Simplify();
- return *this;
- }
+ // this = v + t + (a)
+ // -> v + (a) + t
- if (m_next->m_op == MULTIPLY) // (a*b) - c == (a-[c/b]) * b
- insert->operator/=(*m_next);
- else
- insert->operator*=(*m_next); // (a/b) - c == (a-[c*b])/b
+ ParanoidNumber * nt = m_next_term;
+ ParanoidNumber * nf = m_next_factor;
- if (insert->m_next != NULL) // neither of the above simplified
+ ParanoidNumber ca(a, SUBTRACT);
+ if (m_next_factor != NULL)
{
- //Debug("{%s} did not simplify, change back to {%s}", insert->Str().c_str(), a.Str().c_str());
- insert->operator=(a); // Just add as is
- insert->m_op = SUBTRACT;
- ParanoidNumber * n = this;
- while (n->m_next != NULL)
- n = n->m_next;
- n->InsertAfter(insert);
- }
- else
+ if (m_next_factor->m_op == MULTIPLY)
+ ca /= (*m_next_factor);
+ else
+ ca *= (*m_next_factor);
+
+ if (ca.Floating())
+ {
+ m_next_factor = NULL;
+ m_next_term = NULL;
+ operator-=(ca);
+ m_next_factor = nf;
+ m_next_term = nt;
+ Simplify();
+ return *this;
+ }
+
+ }
+
+ m_next_term = new ParanoidNumber(a,SUBTRACT);
+ ParanoidNumber * t = m_next_term;
+ while (t->m_next_term != NULL)
{
- InsertAfter(insert);
+ t->m_op = SUBTRACT;
+ t = t->m_next_term;
}
+ t->m_op = SUBTRACT;
+ //Debug("next term {%s}", m_next_term->Str().c_str());
+ t->m_next_term = nt;
+ //Debug("Simplify {%s} after sub", Str().c_str());
Simplify();
return *this;
}
ParanoidNumber & ParanoidNumber::operator*=(const ParanoidNumber & a)
{
- ParanoidNumber * n = m_next;
- while (n != NULL)
- {
- if (n->m_op == ADD || n->m_op == SUBTRACT)
- {
- n->operator*=(a);
- break;
- }
- n = n->m_next;
- }
-
- InsertAfter(new ParanoidNumber(a, MULTIPLY));
+ Debug("{%s} *= {%s}", Str().c_str(), a.Str().c_str());
+ // this = (vf + t) * (a)
+ ParanoidNumber * nf = m_next_factor;
+ m_next_factor = new ParanoidNumber(a, MULTIPLY);
+ ParanoidNumber * t = m_next_factor;
+ while (t->m_next_factor != NULL)
+ t = t->m_next_factor;
+ t->m_next_factor = nf;
+ if (m_next_term != NULL)
+ m_next_term->operator*=(a);
+ //Debug("Simplify after mul");
+ Debug("Simplify {%s}", Str().c_str());
Simplify();
return *this;
}
ParanoidNumber & ParanoidNumber::operator/=(const ParanoidNumber & a)
{
- ParanoidNumber * n = m_next;
- while (n != NULL)
- {
- if (n->m_op == ADD || n->m_op == SUBTRACT)
- {
- n->operator/=(a);
- break;
- }
- n = n->m_next;
- }
-
- InsertAfter(new ParanoidNumber(a, DIVIDE));
+ //Debug("Called %s /= %s", Str().c_str(), a.Str().c_str());
+ // this = (vf + t) * (a)
+ ParanoidNumber * nf = m_next_factor;
+ m_next_factor = new ParanoidNumber(a, DIVIDE);
+ ParanoidNumber * t = m_next_factor;
+ while (t->m_next_factor != NULL)
+ t = t->m_next_factor;
+ t->m_next_factor = nf;
+ if (m_next_term != NULL)
+ m_next_term->operator/=(a);
Simplify();
return *this;
}
-double ParanoidNumber::ToDouble() const
-{
- double value = (m_op == SUBTRACT) ? -m_value : m_value;
- const ParanoidNumber * n = m_next;
- while (n != NULL)
+
+
+void ParanoidNumber::SimplifyTerms()
+{
+ //Debug("Simplify {%s}", Str().c_str());
+ if (m_next_term == NULL)
{
- switch (n->m_op)
+ //Debug("No terms!");
+ return;
+ }
+
+ for (ParanoidNumber * a = this; a != NULL; a = a->m_next_term)
+ {
+ ParanoidNumber * bprev = a;
+ ParanoidNumber * b = a->m_next_term;
+ while (b != NULL)
{
- case ADD:
- case SUBTRACT:
- return value + n->ToDouble();
- break;
- case MULTIPLY:
- value *= n->m_value;
- break;
- case DIVIDE:
- value /= n->m_value;
- break;
+ //Debug("Simplify factors of %s", b->Str().c_str());
+ b->SimplifyFactors();
+ if (b->m_next_factor != NULL)
+ {
+ bprev = b;
+ b = b->m_next_term;
+ continue;
+ }
+ float f = a->m_value;
+ feclearexcept(FE_ALL_EXCEPT);
+ switch (b->m_op)
+ {
+ case ADD:
+ f += b->m_value;
+ break;
+ case SUBTRACT:
+ f -= b->m_value;
+ break;
+ default:
+ Fatal("Unexpected %c in term list...", OpChar(b->m_op));
+ break;
+ }
+ if (!fetestexcept(FE_ALL_EXCEPT))
+ {
+ a->m_value = f;
+ bprev->m_next_term = b->m_next_term;
+ b->m_next_term = NULL;
+ delete b;
+ b = bprev;
+ }
+ bprev = b;
+ b = b->m_next_term;
}
- n = n->m_next;
}
- return value;
}
-void ParanoidNumber::Simplify()
-{
- ParanoidNumber * n = m_next;
- ParanoidNumber * p = this;
-
- while (n != NULL)
+void ParanoidNumber::SimplifyFactors()
+{
+ //Debug("Simplify {%s}", Str().c_str());
+ if (m_next_factor == NULL)
{
-
- float a = p->m_value;
- switch (n->m_op)
+ //Debug("No factors!");
+ return;
+ }
+
+ for (ParanoidNumber * a = this; a != NULL; a = a->m_next_factor)
+ {
+ ParanoidNumber * bprev = a;
+ ParanoidNumber * b = a->m_next_factor;
+ while (b != NULL)
{
- case ADD:
- n->Simplify();
- feclearexcept(FE_ALL_EXCEPT);
- a += n->m_value;
- break;
- case SUBTRACT:
- n->Simplify();
- feclearexcept(FE_ALL_EXCEPT);
- a -= n->m_value;
- break;
- case MULTIPLY:
- feclearexcept(FE_ALL_EXCEPT);
- a *= n->m_value;
- break;
- case DIVIDE:
- feclearexcept(FE_ALL_EXCEPT);
- a /= n->m_value;
- break;
+ b->SimplifyTerms();
+ if (b->m_next_term != NULL)
+ {
+ bprev = b;
+ b = b->m_next_factor;
+ continue;
+ }
+ float f = a->m_value;
+ feclearexcept(FE_ALL_EXCEPT);
+ switch (b->m_op)
+ {
+ case MULTIPLY:
+ if (a->m_op != DIVIDE)
+ f *= b->m_value;
+ else
+ f /= b->m_value;
+ break;
+ case DIVIDE:
+ if (a->m_op != DIVIDE)
+ f /= b->m_value;
+ else
+ f *= b->m_value;
+ break;
+ default:
+ Fatal("Unexpected %c in factor list...",OpChar(b->m_op));
+ break;
+ }
+ if (!fetestexcept(FE_ALL_EXCEPT))
+ {
+ a->m_value = f;
+ bprev->m_next_factor = b->m_next_factor;
+ b->m_next_factor = NULL;
+ delete b;
+ b = bprev;
+ }
+ //else
+ //Debug("Failed to simplify %f %c %f", a->m_value, OpChar(b->m_op), b->m_value);
+ bprev = b;
+ b = b->m_next_factor;
}
- // can't merge p and n
- if (fetestexcept(FE_ALL_EXCEPT))
- {
- while (n != NULL && n->m_op != ADD && n->m_op != SUBTRACT)
- n = n->m_next;
- if (n != NULL)
- n->Simplify();
- return;
- }
- else
- {
- // merge n into p
- p->m_value = a;
- p->m_next = n->m_next;
- n->m_next = NULL;
- delete n;
- n = p->m_next;
- }
- //Debug(" -> {%s}", Str().c_str());
}
}
+void ParanoidNumber::Simplify()
+{
+ SimplifyFactors();
+ SimplifyTerms();
+}
+
string ParanoidNumber::Str() const
{
string result("");
- switch (m_op)
+ stringstream s;
+
+ s << m_value;
+
+ if (m_next_factor != NULL)
{
- case ADD:
- result += " +";
- break;
- case SUBTRACT:
- result += " -";
- break;
- case MULTIPLY:
- result += " *";
- break;
- case DIVIDE:
- result += " /";
- break;
+ result += OpChar(m_op);
+ result += "(";
+ result += s.str();
+ result += m_next_factor->Str();
+ result += ")";
+ }
+ else
+ {
+ result += OpChar(m_op);
+ result += s.str();
+ }
+
+ if (m_next_term != NULL)
+ {
+ result += " ";
+ result += m_next_term->Str();
}
- stringstream s("");
- s << m_value;
- result += s.str();
- if (m_next != NULL)
- result += m_next->Str();
return result;
}
#include <cfloat>
#include <map>
#include <string>
+#include "log.h"
+
+
namespace IPDF
{
public:
typedef enum {ADD, SUBTRACT, MULTIPLY, DIVIDE} Optype;
- ParanoidNumber(float value=0, Optype type = ADD) : m_value(value), m_op(type), m_next(NULL)
+ ParanoidNumber(float value=0, Optype type = ADD) : m_value(value), m_op(type), m_next_term(NULL), m_next_factor(NULL)
{
}
- ParanoidNumber(const ParanoidNumber & cpy) : m_value(cpy.m_value), m_op(cpy.m_op), m_next(NULL)
+ ParanoidNumber(const ParanoidNumber & cpy) : m_value(cpy.m_value), m_op(cpy.m_op), m_next_term(NULL), m_next_factor(NULL)
{
- if (cpy.m_next != NULL)
+ if (cpy.m_next_term != NULL)
{
- m_next = new ParanoidNumber(*(cpy.m_next));
+ m_next_term = new ParanoidNumber(*(cpy.m_next_term));
+ }
+ if (cpy.m_next_factor != NULL)
+ {
+ m_next_factor = new ParanoidNumber(*(cpy.m_next_factor));
}
}
- ParanoidNumber(const ParanoidNumber & cpy, Optype type) : ParanoidNumber(cpy)
+ ParanoidNumber(const ParanoidNumber & cpy, Optype type) : m_value(cpy.m_value), m_op(type), m_next_term(NULL), m_next_factor(NULL)
{
- m_op = type;
+ if (cpy.m_next_term != NULL)
+ {
+ m_next_term = new ParanoidNumber(*(cpy.m_next_term));
+ }
+ if (cpy.m_next_factor != NULL)
+ {
+ m_next_factor = new ParanoidNumber(*(cpy.m_next_factor));
+ }
}
ParanoidNumber(const char * str);
+ ParanoidNumber(const std::string & str) : ParanoidNumber(str.c_str()) {}
virtual ~ParanoidNumber()
{
- if (m_next != NULL)
- delete m_next;
+ if (m_next_term != NULL)
+ delete m_next_term;
+ if (m_next_factor != NULL)
+ delete m_next_factor;
}
+ template <class T> T Convert() const;
+ double ToDouble() const {return Convert<double>();}
+ float ToFloat() const {return Convert<float>();}
- double ToDouble() const;
+ bool Floating() const {return (m_next_term == NULL && m_next_factor == NULL);}
+ bool Sunken() const {return !Floating();} // I could not resist...
ParanoidNumber & operator+=(const ParanoidNumber & a);
ParanoidNumber & operator-=(const ParanoidNumber & a);
}
std::string Str() const;
+ static char OpChar(Optype op)
+ {
+ static char opch[] = {'+','-','*','/'};
+ return opch[(int)op];
+ }
private:
void Simplify();
- ParanoidNumber * InsertAfter(ParanoidNumber * insert);
- ParanoidNumber * InsertAfter(float value, Optype op);
+ void SimplifyTerms();
+ void SimplifyFactors();
+
float m_value;
Optype m_op;
- ParanoidNumber * m_next;
+ ParanoidNumber * m_next_term;
+ ParanoidNumber * m_next_factor;
+
+
};
+template <class T>
+T ParanoidNumber::Convert() const
+{
+ T value = (m_op == SUBTRACT) ? -m_value : m_value;
+ const ParanoidNumber * n = m_next_factor;
+ if (n != NULL)
+ {
+ switch (n->m_op)
+ {
+ case MULTIPLY:
+ value *= n->Convert<T>();
+ break;
+ case DIVIDE:
+ value /= n->Convert<T>();
+ break;
+ default:
+ Fatal("Shouldn't happen");
+ break;
+ }
+ }
+ n = m_next_term;
+ if (n != NULL)
+ {
+ switch (n->m_op)
+ {
+ case ADD:
+ case SUBTRACT:
+ value += n->Convert<T>();
+ break;
+ default:
+ Fatal("Shouldn't happen");
+ }
+ }
+ return value;
+}
+
+
}
#endif //_PARANOIDNUMBER_H
{
ymax = (objb.y+objb.h);
bottom = i;
- }
-
- // find fill points
- Vec2 pt;
- // left
- pt = Vec2(objb.x, objb.y+objb.h/Real(2));
- if (PointInside(objects, pt))
- m_fill_points.push_back(pt);
- // right
- pt = Vec2(objb.x+objb.w, objb.y+objb.h/Real(2));
- if (PointInside(objects, pt))
- m_fill_points.push_back(pt);
- // bottom
- pt = Vec2(objb.x+objb.w/Real(2), objb.y+objb.h);
- if (PointInside(objects, pt))
- m_fill_points.push_back(pt);
- // top
- pt = Vec2(objb.x+objb.w/Real(2), objb.y);
- if (PointInside(objects, pt))
- m_fill_points.push_back(pt);
-
- // topleft
- pt = Vec2(objb.x, objb.y);
- if (PointInside(objects, pt))
- m_fill_points.push_back(pt);
- // topright
- pt = Vec2(objb.x+objb.w, objb.y);
- if (PointInside(objects, pt))
- m_fill_points.push_back(pt);
- // bottom left
- pt = Vec2(objb.x, objb.y+objb.h);
- if (PointInside(objects, pt))
- m_fill_points.push_back(pt);
- // bottom right
- pt = Vec2(objb.x+objb.w, objb.y);
- if (PointInside(objects, pt))
- m_fill_points.push_back(pt);
-
- // mid
- pt = Vec2(objb.x+objb.w/Real(2), objb.y+objb.h/Real(2));
- if (PointInside(objects, pt))
- m_fill_points.push_back(pt);
-
-
+ }
}
// Get actual turning point coords of the 4 edge case beziers
m_top = objects.beziers[objects.data_indices[top]].ToAbsolute(objects.bounds[top]).GetTop();
m_bottom = objects.beziers[objects.data_indices[bottom]].ToAbsolute(objects.bounds[bottom]).GetBottom();
m_left = objects.beziers[objects.data_indices[left]].ToAbsolute(objects.bounds[left]).GetLeft();
- m_right = objects.beziers[objects.data_indices[right]].ToAbsolute(objects.bounds[right]).GetRight();
-
- Vec2 pt = (m_top + m_bottom)/2;
- if (PointInside(objects, pt))
- m_fill_points.push_back(pt);
- pt = (m_left + m_right)/2;
- if (PointInside(objects, pt))
- m_fill_points.push_back(pt);
- pt = (m_left + m_right + m_top + m_bottom)/4;
- if (PointInside(objects, pt))
- m_fill_points.push_back(pt);
-
+ m_right = objects.beziers[objects.data_indices[right]].ToAbsolute(objects.bounds[right]).GetRight();
}
return true;
}
+vector<Vec2> & Path::FillPoints(const Objects & objects, const View & view)
+{
+ if (m_fill_points.size() != 0)
+ return m_fill_points;
+
+
+ for (unsigned i = m_start; i <= m_end; ++i)
+ {
+ const Rect & objb = objects.bounds[i];
+ // find fill points
+ Vec2 pt;
+ // left
+ pt = Vec2(objb.x, objb.y+objb.h/Real(2));
+ if (PointInside(objects, pt))
+ m_fill_points.push_back(pt);
+ // right
+ pt = Vec2(objb.x+objb.w, objb.y+objb.h/Real(2));
+ if (PointInside(objects, pt))
+ m_fill_points.push_back(pt);
+ // bottom
+ pt = Vec2(objb.x+objb.w/Real(2), objb.y+objb.h);
+ if (PointInside(objects, pt))
+ m_fill_points.push_back(pt);
+ // top
+ pt = Vec2(objb.x+objb.w/Real(2), objb.y);
+ if (PointInside(objects, pt))
+ m_fill_points.push_back(pt);
+
+ // topleft
+ pt = Vec2(objb.x, objb.y);
+ if (PointInside(objects, pt))
+ m_fill_points.push_back(pt);
+ // topright
+ pt = Vec2(objb.x+objb.w, objb.y);
+ if (PointInside(objects, pt))
+ m_fill_points.push_back(pt);
+ // bottom left
+ pt = Vec2(objb.x, objb.y+objb.h);
+ if (PointInside(objects, pt))
+ m_fill_points.push_back(pt);
+ // bottom right
+ pt = Vec2(objb.x+objb.w, objb.y);
+ if (PointInside(objects, pt))
+ m_fill_points.push_back(pt);
+
+ // mid
+ pt = Vec2(objb.x+objb.w/Real(2), objb.y+objb.h/Real(2));
+ if (PointInside(objects, pt))
+ m_fill_points.push_back(pt);
+
+
+ }
+
+ // 4 extrema
+ Vec2 pt = (m_top + m_bottom)/2;
+ if (PointInside(objects, pt))
+ m_fill_points.push_back(pt);
+ pt = (m_left + m_right)/2;
+ if (PointInside(objects, pt))
+ m_fill_points.push_back(pt);
+ pt = (m_left + m_right + m_top + m_bottom)/4;
+ if (PointInside(objects, pt))
+ m_fill_points.push_back(pt);
+
+ return m_fill_points;
+}
+
Rect Path::SolveBounds(const Objects & objects) const
{
return Rect(m_left.x, m_top.y, m_right.x-m_left.x, m_bottom.y-m_top.y);
};
class Objects;
+ class View;
struct Path
{
Path(const Objects & objects, unsigned _start, unsigned _end, const Colour & _fill = Colour(128,128,128,255), const Colour & _stroke = Colour(0,0,0,0));
Rect SolveBounds(const Objects & objects) const;
+ std::vector<Vec2> & FillPoints(const Objects & objects, const View & view);
// Is point inside shape?
bool PointInside(const Objects & objects, const Vec2 & pt, bool debug=false) const;
"long double",
"VFPU",
"Rational<int64_t>",
- "Rational<Arbint>"
+ "Rational<Arbint>",
+ "mpfrc++ real"
};
#if REAL == REAL_RATIONAL_ARBINT
#define REAL_VFPU 3
#define REAL_RATIONAL 4
#define REAL_RATIONAL_ARBINT 5
+#define REAL_MPFRCPP 6
#ifndef REAL
#error "REAL was not defined!"
#include "gmpint.h"
#endif //REAL
+#if REAL == REAL_MPFRCPP
+ #include <mpreal.h>
+#endif //REAL
+
namespace IPDF
{
extern const char * g_real_name[];
inline double Double(const Real & r) {return r.ToDouble();}
inline int64_t Int64(const Real & r) {return r.ToInt64();}
inline Rational<ARBINT> Sqrt(const Rational<ARBINT> & r) {return r.Sqrt();}
-
+#elif REAL == REAL_MPFRCPP
+ typedef mpfr::mpreal Real;
+ inline double Double(const Real & r) {return r.toDouble();}
+ inline float Float(const Real & r) {return r.toDouble();}
+ inline int64_t Int64(const Real & r) {return r.toLong();}
+ inline Real Sqrt(const Real & r) {return mpfr::sqrt(r, mpfr::mpreal::get_default_rnd());}
+ inline Real Abs(const Real & r) {return mpfr::abs(r, mpfr::mpreal::get_default_rnd());}
#else
#error "Type of Real unspecified."
#endif //REAL
int main(int argc, char ** argv)
{
- while (true)
+ while (cin.good())
{
double da; double db;
char op;
Debug("FLT_MIN = %.40f", FLT_MIN);
Debug("FLT_EPSILON = %.40f", FLT_EPSILON);
- while (true)
+ while (cin.good())
{
float a; float b;
char op;
Debug("FLT_EPSILON = %.40f", FLT_EPSILON);
ParanoidNumber a("0.3");
- Debug("start at %s", a.Str().c_str());
+ Debug("start at {%s} = %lf", a.Str().c_str(), a.ToDouble());
cout << "0.3 ";
float fa = 0.3;
double da = 0.3;
while (cin.good())
{
char op;
- double db;
- cin >> op >> db;
- float fb(db);
- ParanoidNumber b(fb);
+ cin >> op;
+ string token("");
+ for (char c = cin.peek(); cin.good() && !iswspace(c); c = cin.peek())
+ {
+ if (c == '+' || c == '-' || c == '*' || c == '/')
+ {
+ break;
+ }
+ token += c;
+ c = cin.get();
+ }
+ Debug("String is %s", token.c_str());
+ float fb = strtof(token.c_str(), NULL);
+ double db = strtod(token.c_str(), NULL);
+ ParanoidNumber b(token.c_str());
+ Debug("b is {%s} %lf", b.Str().c_str(), b.ToDouble());
switch (op)
{
case '+':
--- /dev/null
+#include "main.h"
+#include "real.h"
+#include <cmath>
+#include <cassert>
+#include <list>
+#include <bitset>
+#include <iostream>
+#include <cfloat>
+#include <fenv.h>
+#include "paranoidnumber.h"
+
+using namespace std;
+using namespace IPDF;
+
+string RandomNumberAsString(int digits = 6)
+{
+ string result("");
+ int dp = 1+(rand() % 3);
+ for (int i = 0; i < digits; ++i)
+ {
+ if (i == dp)
+ {
+ result += ".";
+ continue;
+ }
+ result += ('0'+rand() % 10);
+ }
+ return result;
+}
+
+#define TEST_CASES 10000
+
+int main(int argc, char ** argv)
+{
+
+ string number(RandomNumberAsString());
+ ParanoidNumber a(number);
+ float fa = strtof(number.c_str(), NULL);
+ double da = strtod(number.c_str(), NULL);
+ long double lda = strtold(number.c_str(), NULL);
+
+ if (fabs(a.ToDouble() - da) > 1e-6)
+ {
+ Error("double %lf, pn %lf {%s}", da, a.ToDouble(), a.Str().c_str());
+ Fatal("Didn't construct correctly off %s", number.c_str());
+ }
+
+ char opch[] = {'+','-','*','/'};
+
+ for (int i = 0; i < TEST_CASES; ++i)
+ {
+ number = RandomNumberAsString();
+ ParanoidNumber b(number);
+ float fb = strtof(number.c_str(), NULL);
+ double db = strtod(number.c_str(), NULL);
+ long double ldb = strtold(number.c_str(), NULL);
+ int op = (rand() % 4);
+ ParanoidNumber olda(a);
+ double oldda(da);
+ switch (op)
+ {
+ case 0:
+ a += b;
+ fa += fb;
+ da += db;
+ lda += ldb;
+ break;
+ case 1:
+ a -= b;
+ fa -= fb;
+ da -= db;
+ lda -= ldb;
+ break;
+ case 2:
+ a *= b;
+ fa *= fb;
+ da *= db;
+ lda *= ldb;
+ break;
+ case 3:
+ a /= b;
+ fa /= fb;
+ da /= db;
+ lda /= ldb;
+ break;
+ }
+ if (fabs(a.ToDouble() - da) > 1.0 )
+ {
+ Error("Op %i: ParanoidNumber probably doesn't work", i);
+ Error("Operation: %lf %c %lf", oldda, opch[op], db);
+ Error("As PN: %lf %c %lf", olda.ToDouble(), opch[op], b.ToDouble());
+ Fatal("%lf, expected aboout %lf", a.ToDouble(), da);
+ }
+ }
+ printf("ParanoidNumber: {%s} = %.40lf\n", a.Str().c_str(), a.ToDouble());
+ printf("float: %.40f\n", fa);
+ printf("double: %.40lf\n", da);
+ printf("long double: %.40Lf\n", lda);
+}
#ifndef CONTROLPANEL_DISABLED
ControlPanel::Update();
#endif //CONTROLPANEL_DISABLED
+ //Debug("Completed Render");
}