// mandel.cpp
+#include <QDebug>
+
#include "colors.h"
#include "mandel.h"
+MpzPoint::MpzPoint() : x(), y() {}
+MpzPoint::MpzPoint(mpz_class x, mpz_class y) : x(x), y(y) {}
+MpzPoint::MpzPoint(const MpzPoint &other) : x(other.x), y(other.y) {}
+
MandelResultCell::MandelResultCell() {}
-MandelResultCell::MandelResultCell(size_t iter, QPointF rpos)
+MandelResultCell::MandelResultCell(size_t iter, MpzPoint rpos)
: iter(iter), rpos(rpos) {}
static inline void incrpos(QPoint &pos, const int width) {
}
}
+static inline mpz_class get_one(const QSize size) {
+ int one = std::min(size.width() / 3, size.height() / 3) / 2;
+ one--;
+ one |= one >> 1;
+ one |= one >> 2;
+ one |= one >> 4;
+ one |= one >> 8;
+ one |= one >> 16;
+ return mpz_class(one + 1);
+}
+
MandelMeta::MandelMeta(size_t max_iter, const QSize size)
: max_iter(max_iter),
img(size, QImage::Format_RGB888),
cells(size.width() * size.height(), MandelCell(this)),
- center_f(qreal(-3) / 4, 0),
- one(1),
- four(4),
- scale(std::max(qreal(3) / size.width(), qreal(3) / size.height()))
+ one(::get_one(size))
{
QVector<MandelCell>::iterator i;
QPointF c(size.width() / 2., size.height() / 2.);
QPoint pos;
+ center_f = MpzPoint(one * -3 / 4, 0);
for (i = cells.begin(); i != cells.end(); incrpos(pos, size.width()), i++) {
i->set_meta(this);
i->set_pos(pos);
void MandelMeta::zoom2x(QPoint pos) {
QVector<MandelCell>::iterator i;
- center_f = cells[img.width() * pos.y() + pos.x()].get_rpos0();
- scale /= 2;
+ MpzPoint p = cells[img.width() * pos.y() + pos.x()].get_rpos0();
+ center_f = MpzPoint(p.get_x() * 8, p.get_y() * 8);
+ one *= 8;
img.fill(Qt::GlobalColor::black);
for (i = cells.begin(); i != cells.end(); i++)
i->reset_iter_and_rpos();
}
void MandelCell::reset_rpos0() {
- QPointF center_f = meta->get_center_f();
- rpos0 = QPointF(
- center_f.x() + (pos.x() - meta->get_width() / 2.) * meta->get_scale(),
- center_f.y() + (pos.y() - meta->get_height() / 2.) * meta->get_scale()
+ MpzPoint center_f = meta->get_center_f();
+ rpos0 = MpzPoint(
+ center_f.get_x() + (pos.x() - meta->get_width() / 2.),
+ center_f.get_y() + (pos.y() - meta->get_height() / 2.)
);
}
: meta(cell.meta), pos(cell.pos), iter(cell.iter),
rpos(cell.rpos), rpos0(cell.rpos0) {}
-QPoint MandelCell::update_result(size_t iter, const QPointF &rpos) {
+QPoint MandelCell::update_result(size_t iter, const MpzPoint &rpos) {
this->iter = iter;
this->rpos = rpos;
return pos;
void MandelCell::reset_iter_and_rpos() {
iter = 0;
- rpos = QPointF();
+ rpos = MpzPoint();
reset_rpos0();
}
}
MandelResultCell MandelCell::iterate() const {
+ MpzPoint rpos = this->rpos, sq;
+ mpz_class one = meta->get_one(), four = one * one * 4;
+ mpz_class sqx, sqy;
size_t iter = this->iter;
- QPointF rpos = this->rpos, sq;
- for (; iter < this->meta->get_max_iter(); iter++) {
- sq = QPointF(rpos.x() * rpos.x(), rpos.y() * rpos.y());
- if (sq.x() + sq.y() > meta->get_four())
+ for (; iter < meta->get_max_iter(); iter++) {
+ sqx = rpos.get_x() * rpos.get_x();
+ sqy = rpos.get_y() * rpos.get_y();
+ if (sqx + sqy > four)
break;
- rpos = QPointF(
- sq.x() - sq.y() + rpos0.x(),
- 2 * rpos.x() * rpos.y() + rpos0.y()
+ rpos = MpzPoint(
+ (sqx - sqy) / one + rpos0.get_x(),
+ rpos.get_x() * rpos.get_y() * 2 / one + rpos0.get_y()
);
}
return MandelResultCell(iter, rpos);
#include <QPixmap>
#include <QPoint>
#include <QVector>
+#include <gmpxx.h>
class MandelCell;
+class MpzPoint {
+ mpz_class x, y;
+public:
+ MpzPoint();
+ MpzPoint(mpz_class x, mpz_class y);
+ MpzPoint(const MpzPoint &other);
+ const mpz_class get_x() const { return x; }
+ const mpz_class get_y() const { return y; }
+};
+
class MandelResultCell {
friend class MandelMeta;
size_t iter;
- QPointF rpos;
+ MpzPoint rpos;
public:
MandelResultCell();
- MandelResultCell(size_t iter, QPointF rpos);
+ MandelResultCell(size_t iter, MpzPoint rpos);
};
class MandelMeta {
size_t max_iter;
QImage img;
QVector<MandelCell> cells;
- QPointF center_f;
- qreal one, four, scale;
+ MpzPoint center_f;
+ mpz_class one;
public:
MandelMeta(size_t max_iter, QSize size);
const int get_height() const { return img.height(); }
const QSize get_size() const { return img.size(); }
const QVector<MandelCell> get_cells() const { return cells; }
- const QPointF get_center_f() const { return center_f; }
- const qreal get_four() const { return four; }
- const qreal get_scale() const { return scale; }
+ const MpzPoint get_center_f() const { return center_f; }
+ const mpz_class get_one() const { return one; }
void zoom2x(QPoint pos);
void finished_cell(int num, const MandelResultCell &cell);
MandelMeta *meta;
QPoint pos;
size_t iter;
- QPointF rpos, rpos0;
+ MpzPoint rpos, rpos0;
protected:
void reset_rpos0();
MandelCell(MandelMeta *meta);
MandelCell(const MandelCell &cell);
inline const size_t get_iter() const { return iter; }
- inline const QPointF get_rpos0() const { return rpos0; }
+ inline const MpzPoint get_rpos0() const { return rpos0; }
- QPoint update_result(size_t iter, const QPointF &rpos);
+ QPoint update_result(size_t iter, const MpzPoint &rpos);
void reset_iter_and_rpos();
void set_meta(MandelMeta *meta);
void set_pos(const QPoint pos);