]> git.mar77i.info Git - bigintmandel/blob - mandel.cpp
use gmp big ints rather than qreal
[bigintmandel] / mandel.cpp
1
2 // mandel.cpp
3
4 #include <QDebug>
5
6 #include "colors.h"
7 #include "mandel.h"
8
9 MpzPoint::MpzPoint() : x(), y() {}
10 MpzPoint::MpzPoint(mpz_class x, mpz_class y) : x(x), y(y) {}
11 MpzPoint::MpzPoint(const MpzPoint &other) : x(other.x), y(other.y) {}
12
13 MandelResultCell::MandelResultCell() {}
14
15 MandelResultCell::MandelResultCell(size_t iter, MpzPoint rpos)
16 : iter(iter), rpos(rpos) {}
17
18 static inline void incrpos(QPoint &pos, const int width) {
19 pos.setX(pos.x() + 1);
20 if (pos.x() == width) {
21 pos.setX(0);
22 pos.setY(pos.y() + 1);
23 }
24 }
25
26 static inline mpz_class get_one(const QSize size) {
27 int one = std::min(size.width() / 3, size.height() / 3) / 2;
28 one--;
29 one |= one >> 1;
30 one |= one >> 2;
31 one |= one >> 4;
32 one |= one >> 8;
33 one |= one >> 16;
34 return mpz_class(one + 1);
35 }
36
37 MandelMeta::MandelMeta(size_t max_iter, const QSize size)
38 : max_iter(max_iter),
39 img(size, QImage::Format_RGB888),
40 cells(size.width() * size.height(), MandelCell(this)),
41 one(::get_one(size))
42 {
43 QVector<MandelCell>::iterator i;
44 QPointF c(size.width() / 2., size.height() / 2.);
45 QPoint pos;
46
47 center_f = MpzPoint(one * -3 / 4, 0);
48 for (i = cells.begin(); i != cells.end(); incrpos(pos, size.width()), i++) {
49 i->set_meta(this);
50 i->set_pos(pos);
51 }
52 }
53
54 void MandelMeta::zoom2x(QPoint pos) {
55 QVector<MandelCell>::iterator i;
56 MpzPoint p = cells[img.width() * pos.y() + pos.x()].get_rpos0();
57 center_f = MpzPoint(p.get_x() * 8, p.get_y() * 8);
58 one *= 8;
59 img.fill(Qt::GlobalColor::black);
60 for (i = cells.begin(); i != cells.end(); i++)
61 i->reset_iter_and_rpos();
62 }
63
64 void MandelMeta::finished_cell(int num, const MandelResultCell &cell) {
65 img.setPixelColor(
66 cells[num].update_result(cell.iter, cell.rpos),
67 cell.iter < max_iter
68 ? colors[cell.iter % colors.size()]
69 : Qt::GlobalColor::black
70 );
71 }
72
73 MandelResultCell MandelMeta::iterate(const MandelCell &cell) {
74 return cell.iterate();
75 }
76
77 void MandelCell::reset_rpos0() {
78 MpzPoint center_f = meta->get_center_f();
79 rpos0 = MpzPoint(
80 center_f.get_x() + (pos.x() - meta->get_width() / 2.),
81 center_f.get_y() + (pos.y() - meta->get_height() / 2.)
82 );
83 }
84
85 MandelCell::MandelCell(MandelMeta *meta) : meta(meta), iter(0) {}
86
87 MandelCell::MandelCell(const MandelCell &cell)
88 : meta(cell.meta), pos(cell.pos), iter(cell.iter),
89 rpos(cell.rpos), rpos0(cell.rpos0) {}
90
91 QPoint MandelCell::update_result(size_t iter, const MpzPoint &rpos) {
92 this->iter = iter;
93 this->rpos = rpos;
94 return pos;
95 }
96
97 void MandelCell::reset_iter_and_rpos() {
98 iter = 0;
99 rpos = MpzPoint();
100 reset_rpos0();
101 }
102
103 void MandelCell::set_meta(MandelMeta *meta) {
104 this->meta = meta;
105 }
106
107 void MandelCell::set_pos(QPoint pos) {
108 this->pos = pos;
109 reset_rpos0();
110 }
111
112 MandelResultCell MandelCell::iterate() const {
113 MpzPoint rpos = this->rpos, sq;
114 mpz_class one = meta->get_one(), four = one * one * 4;
115 mpz_class sqx, sqy;
116 size_t iter = this->iter;
117 for (; iter < meta->get_max_iter(); iter++) {
118 sqx = rpos.get_x() * rpos.get_x();
119 sqy = rpos.get_y() * rpos.get_y();
120 if (sqx + sqy > four)
121 break;
122 rpos = MpzPoint(
123 (sqx - sqy) / one + rpos0.get_x(),
124 rpos.get_x() * rpos.get_y() * 2 / one + rpos0.get_y()
125 );
126 }
127 return MandelResultCell(iter, rpos);
128 }