Skip to content

Commit 7f7ebc3

Browse files
committed
added ufuncs, castings and scalar ops
1 parent 96ee075 commit 7f7ebc3

File tree

10 files changed

+1052
-71
lines changed

10 files changed

+1052
-71
lines changed

mandelbrot.py

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
import numpy as np
2+
from quaddtype import QuadPrecDType, QuadPrecision
3+
import matplotlib.pyplot as plt
4+
5+
6+
def get_color(t, interior_t):
7+
epsilon = QuadPrecision("1e-10")
8+
9+
if abs(t - QuadPrecision(1.0)) < epsilon:
10+
value = int(255 * interior_t)
11+
return np.array([value, value, value], dtype=np.uint8)
12+
13+
t = np.power(t, 0.5)
14+
t = np.mod(t * 20, 1.0)
15+
16+
if t < 0.16:
17+
return np.array([0, int(255 * (t / 0.16)), int(128 + 127 * (t / 0.16))], dtype=np.uint8)
18+
elif t < 0.33:
19+
return np.array([0, 255, int(255 * (1 - (t - 0.16) / 0.17))], dtype=np.uint8)
20+
elif t < 0.5:
21+
return np.array([int(255 * ((t - 0.33) / 0.17)), 255, 0], dtype=np.uint8)
22+
elif t < 0.66:
23+
return np.array([255, int(255 * (1 - (t - 0.5) / 0.16)), 0], dtype=np.uint8)
24+
elif t < 0.83:
25+
return np.array([255, 0, int(255 * ((t - 0.66) / 0.17))], dtype=np.uint8)
26+
else:
27+
return np.array([int(255 * (1 - (t - 0.83) / 0.17)), 0, int(128 * ((t - 0.83) / 0.17))], dtype=np.uint8)
28+
29+
30+
def iterate_and_compute_derivatives(cr, ci, max_iter):
31+
zr, zi = 0.0, 0.0
32+
dzr, dzi = 1.0, 0.0
33+
dcr, dci = 0.0, 0.0
34+
dzdzr, dzdzi = 0.0, 0.0
35+
36+
for _ in range(max_iter):
37+
dzdzr_new = 2 * (zr * dzdzr - zi * dzdzi + dzr * dzr - dzi * dzi)
38+
dzdzi_new = 2 * (zr * dzdzi + zi * dzdzr + 2 * dzr * dzi)
39+
dzr_new = 2 * (zr * dzr - zi * dzi) + dcr
40+
dzi_new = 2 * (zr * dzi + zi * dzr) + dci
41+
zr_new = zr * zr - zi * zi + cr
42+
zi_new = 2 * zr * zi + ci
43+
44+
dzdzr, dzdzi = dzdzr_new, dzdzi_new
45+
dzr, dzi = dzr_new, dzi_new
46+
zr, zi = zr_new, zi_new
47+
dcr, dci = 1.0, 0.0
48+
49+
return zr, zi, dzr, dzi, dcr, dci, dzdzr, dzdzi
50+
51+
52+
def estimate_interior_distance(cr, ci, max_iter):
53+
zr, zi, dzr, dzi, dcr, dci, dzdzr, dzdzi = iterate_and_compute_derivatives(
54+
cr, ci, max_iter)
55+
56+
dz_abs_sq = dzr * dzr + dzi * dzi
57+
numerator = 1 - dz_abs_sq
58+
59+
denominator = np.abs((dcr * dzr + dci * dzi) +
60+
(dzdzr * zr + dzdzi * zi) * dcr)
61+
62+
return numerator / denominator
63+
64+
65+
def mandelbrot(cr, ci, max_iter, radius2):
66+
zr, zi = QuadPrecision(0.0), QuadPrecision(0.0)
67+
for i in range(max_iter):
68+
zr_new = zr * zr - zi * zi + cr
69+
zi_new = QuadPrecision(2) * zr * zi + ci
70+
zr, zi = zr_new, zi_new
71+
if zr * zr + zi * zi > radius2:
72+
log_zn = np.log(zr * zr + zi * zi) / QuadPrecision(2)
73+
nu = np.log(log_zn / np.log(QuadPrecision(2))) / \
74+
np.log(QuadPrecision(2))
75+
return i + QuadPrecision(1) - nu, zr, zi
76+
return max_iter, zr, zi
77+
78+
79+
def mandelbrot_set(width, height, max_iter, center_r, center_i, zoom):
80+
radius = QuadPrecision(2.0)
81+
radius2 = radius * radius
82+
zoom = 1 / zoom
83+
84+
x = np.linspace(np.float64(center_r - radius / zoom),
85+
np.float64(center_r + radius / zoom),
86+
width)
87+
y = np.linspace(np.float64(center_i - radius / zoom),
88+
np.float64(center_i + radius / zoom),
89+
height)
90+
cr, ci = np.meshgrid(x, y)
91+
92+
smooth_iter = np.zeros((height, width), dtype=QuadPrecDType)
93+
final_zr = np.zeros((height, width), dtype=QuadPrecDType)
94+
final_zi = np.zeros((height, width), dtype=QuadPrecDType)
95+
96+
for i in range(height):
97+
for j in range(width):
98+
smooth_iter[i, j], final_zr[i, j], final_zi[i, j] = mandelbrot(
99+
cr[i, j], ci[i, j], max_iter, radius2)
100+
101+
img = np.zeros((height, width, 3), dtype=np.uint8)
102+
103+
interior_mask = smooth_iter == QuadPrecision(max_iter)
104+
interior_cr = cr[interior_mask]
105+
interior_ci = ci[interior_mask]
106+
interior_distance = np.array([estimate_interior_distance(
107+
cr, ci, max_iter) for cr, ci in zip(interior_cr, interior_ci)])
108+
interior_t = (interior_distance -
109+
np.floor(interior_distance)).astype(np.float64)
110+
111+
exterior_mask = ~interior_mask
112+
t = smooth_iter[exterior_mask] / QuadPrecision(max_iter)
113+
114+
interior_colors = np.array(
115+
[get_color(QuadPrecision(1.0), t) for t in interior_t])
116+
exterior_colors = np.array([get_color(t, QuadPrecision(0.0)) for t in t])
117+
118+
img[interior_mask] = interior_colors
119+
img[exterior_mask] = exterior_colors
120+
121+
return img
122+
123+
124+
def plot_mandelbrot(width, height, max_iter, center_r, center_i, zoom):
125+
center_rq = QuadPrecision(center_r)
126+
center_iq = QuadPrecision(center_i)
127+
zoom_q = QuadPrecision(zoom)
128+
129+
img_array = mandelbrot_set(
130+
width, height, max_iter, center_rq, center_iq, zoom_q)
131+
132+
plt.figure(figsize=(10, 10))
133+
plt.imshow(img_array)
134+
plt.axis('off')
135+
plt.title(
136+
f'Mandelbrot Set (zoom: {zoom}, center: {center_r} + {center_i}i, iterations: {max_iter}, dtype: numpy.float64)')
137+
plt.show()
138+
139+
140+
if __name__ == "__main__":
141+
width = 800
142+
height = 800
143+
max_iter = 1000
144+
center_r = -0.75
145+
center_i = 0.0
146+
zoom = 1.0
147+
148+
plot_mandelbrot(width, height, max_iter, center_r, center_i, zoom)

0 commit comments

Comments
 (0)