From: mar77i Date: Mon, 1 Apr 2024 09:33:35 +0000 (+0200) Subject: use gmp big ints rather than qreal X-Git-Url: https://git.mar77i.info/?a=commitdiff_plain;h=b04a5fba99e74c447e27c28eea71869725a7c6f4;p=bigintmandel use gmp big ints rather than qreal --- diff --git a/CMakeLists.txt b/CMakeLists.txt index 243407b..8f38274 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -48,6 +48,7 @@ target_link_libraries( PRIVATE Qt${QT_VERSION_MAJOR}::Widgets Qt${QT_VERSION_MAJOR}::Concurrent + gmp ) # Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1. diff --git a/bigintwidget.cpp b/bigintwidget.cpp index c965e0f..88a3889 100644 --- a/bigintwidget.cpp +++ b/bigintwidget.cpp @@ -10,7 +10,7 @@ BigintWidget::BigintWidget(QWidget *parent) : QWidget(parent), fw(new QFutureWatcher(this)), - meta(1024, QSize(1800, 1000)), + meta(8192, QSize(1800, 1000)), img_label(new QLabel(this)), img_dirty(true) { diff --git a/mandel.cpp b/mandel.cpp index e633fb0..795b4e4 100644 --- a/mandel.cpp +++ b/mandel.cpp @@ -1,12 +1,18 @@ // mandel.cpp +#include + #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) { @@ -17,19 +23,28 @@ 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::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); @@ -38,8 +53,9 @@ MandelMeta::MandelMeta(size_t max_iter, const QSize size) void MandelMeta::zoom2x(QPoint pos) { QVector::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(); @@ -59,10 +75,10 @@ MandelResultCell MandelMeta::iterate(const MandelCell &cell) { } 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.) ); } @@ -72,7 +88,7 @@ MandelCell::MandelCell(const MandelCell &cell) : 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; @@ -80,7 +96,7 @@ QPoint MandelCell::update_result(size_t iter, const QPointF &rpos) { void MandelCell::reset_iter_and_rpos() { iter = 0; - rpos = QPointF(); + rpos = MpzPoint(); reset_rpos0(); } @@ -94,15 +110,18 @@ void MandelCell::set_pos(QPoint pos) { } 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); diff --git a/mandel.h b/mandel.h index 487dd0b..99ff14c 100644 --- a/mandel.h +++ b/mandel.h @@ -7,25 +7,36 @@ #include #include #include +#include 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 cells; - QPointF center_f; - qreal one, four, scale; + MpzPoint center_f; + mpz_class one; public: MandelMeta(size_t max_iter, QSize size); @@ -35,9 +46,8 @@ public: const int get_height() const { return img.height(); } const QSize get_size() const { return img.size(); } const QVector 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); @@ -48,7 +58,7 @@ class MandelCell { MandelMeta *meta; QPoint pos; size_t iter; - QPointF rpos, rpos0; + MpzPoint rpos, rpos0; protected: void reset_rpos0(); @@ -57,9 +67,9 @@ public: 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);