Data update

This commit is contained in:
Ingy döt Net 2026-02-01 16:33:20 -08:00
parent 5150844a7d
commit 4bb20c9b71
7735 changed files with 38060 additions and 199180 deletions

View file

@ -1,40 +0,0 @@
with Lumen.Binary;
package body Mandelbrot is
function Create_Image (Width, Height : Natural) return Lumen.Image.Descriptor is
use type Lumen.Binary.Byte;
Result : Lumen.Image.Descriptor;
X0, Y0 : Float;
X, Y, Xtemp : Float;
Iteration : Float;
Max_Iteration : constant Float := 1000.0;
Color : Lumen.Binary.Byte;
begin
Result.Width := Width;
Result.Height := Height;
Result.Complete := True;
Result.Values := new Lumen.Image.Pixel_Matrix (1 .. Width, 1 .. Height);
for Screen_X in 1 .. Width loop
for Screen_Y in 1 .. Height loop
X0 := -2.5 + (3.5 / Float (Width) * Float (Screen_X));
Y0 := -1.0 + (2.0 / Float (Height) * Float (Screen_Y));
X := 0.0;
Y := 0.0;
Iteration := 0.0;
while X * X + Y * Y <= 4.0 and then Iteration < Max_Iteration loop
Xtemp := X * X - Y * Y + X0;
Y := 2.0 * X * Y + Y0;
X := Xtemp;
Iteration := Iteration + 1.0;
end loop;
if Iteration = Max_Iteration then
Color := 255;
else
Color := 0;
end if;
Result.Values (Screen_X, Screen_Y) := (R => Color, G => Color, B => Color, A => 0);
end loop;
end loop;
return Result;
end Create_Image;
end Mandelbrot;

View file

@ -1,7 +0,0 @@
with Lumen.Image;
package Mandelbrot is
function Create_Image (Width, Height : Natural) return Lumen.Image.Descriptor;
end Mandelbrot;

View file

@ -1,155 +0,0 @@
with System.Address_To_Access_Conversions;
with Lumen.Window;
with Lumen.Image;
with Lumen.Events;
with GL;
with Mandelbrot;
procedure Test_Mandelbrot is
Program_End : exception;
Win : Lumen.Window.Handle;
Image : Lumen.Image.Descriptor;
Tx_Name : aliased GL.GLuint;
Wide, High : Natural := 400;
-- Create a texture and bind a 2D image to it
procedure Create_Texture is
use GL;
package GLB is new System.Address_To_Access_Conversions (GLubyte);
IP : GLpointer;
begin -- Create_Texture
-- Allocate a texture name
glGenTextures (1, Tx_Name'Unchecked_Access);
-- Bind texture operations to the newly-created texture name
glBindTexture (GL_TEXTURE_2D, Tx_Name);
-- Select modulate to mix texture with color for shading
glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
-- Wrap textures at both edges
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
-- How the texture behaves when minified and magnified
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-- Create a pointer to the image. This sort of horror show is going to
-- be disappearing once Lumen includes its own OpenGL bindings.
IP := GLB.To_Pointer (Image.Values.all'Address).all'Unchecked_Access;
-- Build our texture from the image we loaded earlier
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, GLsizei (Image.Width), GLsizei (Image.Height), 0,
GL_RGBA, GL_UNSIGNED_BYTE, IP);
end Create_Texture;
-- Set or reset the window view parameters
procedure Set_View (W, H : in Natural) is
use GL;
begin -- Set_View
GL.glEnable (GL.GL_TEXTURE_2D);
glClearColor (0.8, 0.8, 0.8, 1.0);
glMatrixMode (GL_PROJECTION);
glLoadIdentity;
glViewport (0, 0, GLsizei (W), GLsizei (H));
glOrtho (0.0, GLdouble (W), GLdouble (H), 0.0, -1.0, 1.0);
glMatrixMode (GL_MODELVIEW);
glLoadIdentity;
end Set_View;
-- Draw our scene
procedure Draw is
use GL;
begin -- Draw
-- clear the screen
glClear (GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
GL.glBindTexture (GL.GL_TEXTURE_2D, Tx_Name);
-- fill with a single textured quad
glBegin (GL_QUADS);
begin
glTexCoord2f (1.0, 0.0);
glVertex2i (GLint (Wide), 0);
glTexCoord2f (0.0, 0.0);
glVertex2i (0, 0);
glTexCoord2f (0.0, 1.0);
glVertex2i (0, GLint (High));
glTexCoord2f (1.0, 1.0);
glVertex2i (GLint (Wide), GLint (High));
end;
glEnd;
-- flush rendering pipeline
glFlush;
-- Now show it
Lumen.Window.Swap (Win);
end Draw;
-- Simple event handler routine for keypresses and close-window events
procedure Quit_Handler (Event : in Lumen.Events.Event_Data) is
begin -- Quit_Handler
raise Program_End;
end Quit_Handler;
-- Simple event handler routine for Exposed events
procedure Expose_Handler (Event : in Lumen.Events.Event_Data) is
pragma Unreferenced (Event);
begin -- Expose_Handler
Draw;
end Expose_Handler;
-- Simple event handler routine for Resized events
procedure Resize_Handler (Event : in Lumen.Events.Event_Data) is
begin -- Resize_Handler
Wide := Event.Resize_Data.Width;
High := Event.Resize_Data.Height;
Set_View (Wide, High);
-- Image := Mandelbrot.Create_Image (Width => Wide, Height => High);
-- Create_Texture;
Draw;
end Resize_Handler;
begin
-- Create Lumen window, accepting most defaults; turn double buffering off
-- for simplicity
Lumen.Window.Create (Win => Win,
Name => "Mandelbrot fractal",
Width => Wide,
Height => High,
Events => (Lumen.Window.Want_Exposure => True,
Lumen.Window.Want_Key_Press => True,
others => False));
-- Set up the viewport and scene parameters
Set_View (Wide, High);
-- Now create the texture and set up to use it
Image := Mandelbrot.Create_Image (Width => Wide, Height => High);
Create_Texture;
-- Enter the event loop
declare
use Lumen.Events;
begin
Select_Events (Win => Win,
Calls => (Key_Press => Quit_Handler'Unrestricted_Access,
Exposed => Expose_Handler'Unrestricted_Access,
Resized => Resize_Handler'Unrestricted_Access,
Close_Window => Quit_Handler'Unrestricted_Access,
others => No_Callback));
end;
exception
when Program_End =>
null;
end Test_Mandelbrot;

View file

@ -14,8 +14,8 @@ mandelbrot: function [settings][
x: 0
while [x < settings\width][
X: settings\xStart + x * settings\xStep
if? inMandelbrot? to :complex @[X Y] -> prints "*"
else -> prints " "
switch inMandelbrot? to :complex @[X Y] -> prints "*"
-> prints " "
x: x + 1
]
print ""

View file

@ -1,51 +0,0 @@
IDENTIFICATION DIVISION.
PROGRAM-ID. MANDELBROT-SET-PROGRAM.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 COMPLEX-ARITHMETIC.
05 X PIC S9V9(9).
05 Y PIC S9V9(9).
05 X-A PIC S9V9(6).
05 X-B PIC S9V9(6).
05 Y-A PIC S9V9(6).
05 X-A-SQUARED PIC S9V9(6).
05 Y-A-SQUARED PIC S9V9(6).
05 SUM-OF-SQUARES PIC S9V9(6).
05 ROOT PIC S9V9(6).
01 LOOP-COUNTERS.
05 I PIC 99.
05 J PIC 99.
05 K PIC 999.
77 PLOT-CHARACTER PIC X.
PROCEDURE DIVISION.
CONTROL-PARAGRAPH.
PERFORM OUTER-LOOP-PARAGRAPH
VARYING I FROM 1 BY 1 UNTIL I IS GREATER THAN 24.
STOP RUN.
OUTER-LOOP-PARAGRAPH.
PERFORM INNER-LOOP-PARAGRAPH
VARYING J FROM 1 BY 1 UNTIL J IS GREATER THAN 64.
DISPLAY ''.
INNER-LOOP-PARAGRAPH.
MOVE SPACE TO PLOT-CHARACTER.
MOVE ZERO TO X-A.
MOVE ZERO TO Y-A.
MULTIPLY J BY 0.0390625 GIVING X.
SUBTRACT 1.5 FROM X.
MULTIPLY I BY 0.083333333 GIVING Y.
SUBTRACT 1 FROM Y.
PERFORM ITERATION-PARAGRAPH VARYING K FROM 1 BY 1
UNTIL K IS GREATER THAN 100 OR PLOT-CHARACTER IS EQUAL TO '#'.
DISPLAY PLOT-CHARACTER WITH NO ADVANCING.
ITERATION-PARAGRAPH.
MULTIPLY X-A BY X-A GIVING X-A-SQUARED.
MULTIPLY Y-A BY Y-A GIVING Y-A-SQUARED.
SUBTRACT Y-A-SQUARED FROM X-A-SQUARED GIVING X-B.
ADD X TO X-B.
MULTIPLY X-A BY Y-A GIVING Y-A.
MULTIPLY Y-A BY 2 GIVING Y-A.
SUBTRACT Y FROM Y-A.
MOVE X-B TO X-A.
ADD X-A-SQUARED TO Y-A-SQUARED GIVING SUM-OF-SQUARES.
MOVE FUNCTION SQRT (SUM-OF-SQUARES) TO ROOT.
IF ROOT IS GREATER THAN 2 THEN MOVE '#' TO PLOT-CHARACTER.

View file

@ -30,7 +30,7 @@ proc draw .
cx = (scr_x - center_x) / scale
it = iter cx cy maxiter
if it < maxiter
gcolor3 it * 5 it it * 0.7
gcolor3 it * 0.05 it * 0.01 it * 0.007
grect scr_x / res scr_y / res 1 / res 1 / res
.
.

View file

@ -1,42 +0,0 @@
; === Mandelbrot ============================================
(setq mandel-size (cons 76 34))
(setq xmin -2)
(setq xmax .5)
(setq ymin -1.2)
(setq ymax 1.2)
(setq max-iter 20)
(defun mandel-iter-point (x y)
"Run the actual iteration for each point."
(let ((xp 0)
(yp 0)
(it 0)
(xt 0))
(while (and (< (+ (* xp xp) (* yp yp)) 4) (< it max-iter))
(setq xt (+ (* xp xp) (* -1 yp yp) x))
(setq yp (+ (* 2 xp yp) y))
(setq xp xt)
(setq it (1+ it)))
it))
(defun mandel-iter (p)
"Return string for point based on whether inside/outside the set."
(let ((it (mandel-iter-point (car p) (cdr p))))
(if (= it max-iter) "*" "-")))
(defun mandel-pos (x y)
"Convert screen coordinates to input coordinates."
(let ((xp (+ xmin (* (- xmax xmin) (/ (float x) (car mandel-size)))))
(yp (+ ymin (* (- ymax ymin) (/ (float y) (cdr mandel-size))))))
(cons xp yp)))
(defun mandel ()
"Plot the Mandelbrot set."
(dotimes (y (cdr mandel-size))
(dotimes (x (car mandel-size))
(if (= x 0)
(insert(format "\n%s" (mandel-iter (mandel-pos x y))))
(insert(format "%s" (mandel-iter (mandel-pos x y))))))))
(mandel)

View file

@ -1,54 +0,0 @@
; === Graphical Mandelbrot ============================================
(setq mandel-size (cons 320 300))
(setq xmin -2)
(setq xmax .5)
(setq ymin -1.2)
(setq ymax 1.2)
(setq max-iter 20)
(defun mandel-iter-point (x y)
"Run the actual iteration for each point."
(let ((xp 0)
(yp 0)
(it 0)
(xt 0))
(while (and (< (+ (* xp xp) (* yp yp)) 4) (< it max-iter))
(setq xt (+ (* xp xp) (* -1 yp yp) x))
(setq yp (+ (* 2 xp yp) y))
(setq xp xt)
(setq it (1+ it)))
it))
(defun mandel-iter (p)
"Return string for point based on whether inside/outside the set."
(let ((it (mandel-iter-point (car p) (cdr p))))
(if (= it max-iter) "*" (if (cl-oddp it) "+" "-"))))
(defun mandel-pos (x y)
"Convert screen coordinates to input coordinates."
(let ((xp (+ xmin (* (- xmax xmin) (/ (float x) (car mandel-size)))))
(yp (+ ymin (* (- ymax ymin) (/ (float y) (cdr mandel-size))))))
(cons xp yp)))
(defun string-to-image (str)
"Convert image data string to XPM image."
(create-image (concat (format "/* XPM */
static char * mandel[] = {
\"%i %i 3 1\",
\"+ c #ff0000\",
\"- c #0000ff\",
\"* c #000000\"," (car mandel-size) (cdr mandel-size))
str "};") 'xpm t))
(defun mandel-pic ()
"Plot the Mandelbrot set."
(setq all "")
(dotimes (y (cdr mandel-size))
(setq line "")
(dotimes (x (car mandel-size))
(setq line (concat line (mandel-iter (mandel-pos x y)))))
(setq all (concat all "\"" line "\",\n")))
(insert-image (string-to-image all)))
(mandel-pic)

View file

@ -1 +0,0 @@
haxe -swf mandelbrot.swf -main Mandelbrot

View file

@ -1,49 +0,0 @@
class Mandelbrot extends flash.display.Sprite
{
inline static var MAX_ITER = 255;
public static function main() {
var w = flash.Lib.current.stage.stageWidth;
var h = flash.Lib.current.stage.stageHeight;
var mandelbrot = new Mandelbrot(w, h);
flash.Lib.current.stage.addChild(mandelbrot);
mandelbrot.drawMandelbrot();
}
var image:flash.display.BitmapData;
public function new(width, height) {
super();
var bitmap:flash.display.Bitmap;
image = new flash.display.BitmapData(width, height, false);
bitmap = new flash.display.Bitmap(image);
this.addChild(bitmap);
}
public function drawMandelbrot() {
image.lock();
var step_x = 3.0 / (image.width-1);
var step_y = 2.0 / (image.height-1);
for (i in 0...image.height) {
var ci = i * step_y - 1.0;
for (j in 0...image.width) {
var k = 0;
var zr = 0.0;
var zi = 0.0;
var cr = j * step_x - 2.0;
while (k <= MAX_ITER && (zr*zr + zi*zi) <= 4) {
var temp = zr*zr - zi*zi + cr;
zi = 2*zr*zi + ci;
zr = temp;
k ++;
}
paint(j, i, k);
}
}
image.unlock();
}
inline function paint(x, y, iter) {
var color = iter > MAX_ITER? 0 : iter * 0x100;
image.setPixel(x, y, color);
}
}

View file

@ -1,20 +0,0 @@
$x = $y = $i = $j = $r = -16
$colors = [Enum]::GetValues([System.ConsoleColor])
while(($y++) -lt 15)
{
for($x=0; ($x++) -lt 84; Write-Host " " -BackgroundColor ($colors[$k -band 15]) -NoNewline)
{
$i = $k = $r = 0
do
{
$j = $r * $r - $i * $i -2 + $x / 25
$i = 2 * $r * $i + $y / 10
$r = $j
}
while (($j * $j + $i * $i) -lt 11 -band ($k++) -lt 111)
}
Write-Host
}

View file

@ -1,123 +1,8 @@
import numba
numba.config.CUDA_ENABLE_PYNVJITLINK = True # prevent cuda ptx version errors
import numpy as np
import matplotlib.pyplot as plt
import cupy as cp
import numba.cuda as cuda
import decimal as dc # decimal floating point arithmetic with arbitrary precision
dc.getcontext().prec = 80 # set precision to 80 digits (about 256 bits)
d, h = 1600, 1000 # pixel density (= image width) and image height
n, r = 100000, 100000.0 # number of iterations and escape radius (r > 2)
a = dc.Decimal("-1.256827152259138864846434197797294538253477389787308085590211144291")
b = dc.Decimal(".37933802890364143684096784819544060002129071484943239316486643285025")
S = np.zeros(n+1, dtype=np.complex128)
u, v = dc.Decimal(0), dc.Decimal(0)
for i in range(n+1):
S[i] = float(u) + float(v) * 1j
if u * u + v * v < r * r:
u, v = u * u - v * v + a, 2 * u * v + b
else:
print("The reference sequence diverges within %s iterations." % i)
break
x = np.linspace(0, 2, num=d+1, dtype=np.float64)
y = np.linspace(0, 2 * h / d, num=h+1, dtype=np.float64)
A, B = np.meshgrid(x - 1, y - h / d)
C = 5.0e-35 * (A + B * 1j)
def iteration_cupy_cuda(S, C):
I = cp.zeros(C.shape, dtype=np.int32)
E, Z, dZ = cp.zeros_like(C), cp.zeros_like(C), cp.zeros_like(C)
iteration = cp.RawKernel("""
#include <cupy/complex.cuh>
extern "C" __global__
void iterate(int dim_x, int dim_y, int n, double r,
complex<double> *S, complex<double> *C,
int *I, complex<double> *E, complex<double> *Z, complex<double> *dZ) {
int x = blockIdx.x * blockDim.x + threadIdx.x;
int y = blockIdx.y * blockDim.y + threadIdx.y;
if (x < dim_x and y < dim_y) { // prevent memory access errors
int x_y = x * dim_y + y; // cupy arrays are in row-major order
complex<double> delta = C[x_y];
int index = I[x_y];
complex<double> epsilon = E[x_y];
complex<double> z = Z[x_y];
complex<double> dz = dZ[x_y];
double abs2_r = r * r;
double abs2_z, abs2_e;
for (int i = 0; i < n; i++) {
abs2_z = z.real() * z.real() + z.imag() * z.imag();
abs2_e = epsilon.real() * epsilon.real() + epsilon.imag() * epsilon.imag();
if (abs2_z < abs2_e) { // rebase when z is closer to zero
epsilon = z; index = 0; // reset reference orbit
}
if (abs2_z < abs2_r) {
epsilon = (2. * S[index] + epsilon) * epsilon + delta; index = index + 1;
dz = 2. * z * dz + 1.; z = S[index] + epsilon;
}
else {
break;
}
}
I[x_y] = index; E[x_y] = epsilon; Z[x_y] = z; dZ[x_y] = dz;
}
}
""", "iterate")
griddim, blockdim = (h // 32 + 1, d // 32 + 1), (32, 32)
iteration(griddim, blockdim, (h+1, d+1, n, r, cp.asarray(S), cp.asarray(C), I, E, Z, dZ))
return I.get(), E.get(), Z.get(), dZ.get()
def iteration_numba_cuda(S, C):
I = cp.zeros(C.shape, dtype=np.int32)
E, Z, dZ = cp.zeros_like(C), cp.zeros_like(C), cp.zeros_like(C)
@cuda.jit()
def iteration(S, C, I, E, Z, dZ):
x, y = cuda.grid(2)
if x < h+1 and y < d+1: # prevent memory access errors
delta, index, epsilon, z, dz = C[x, y], I[x, y], E[x, y], Z[x, y], dZ[x, y]
def abs2(z):
return z.real * z.real + z.imag * z.imag
for i in range(n):
if abs2(z) < abs2(epsilon): # rebase when z is closer to zero
index, epsilon = 0, z # reset reference orbit
if abs2(z) < abs2(r):
index, epsilon = index + 1, (2 * S[index] + epsilon) * epsilon + delta
z, dz = S[index] + epsilon, 2 * z * dz + 1
else:
break
I[x, y], E[x, y], Z[x, y], dZ[x, y] = index, epsilon, z, dz
griddim, blockdim = (h // 32 + 1, d // 32 + 1), (32, 32)
iteration[griddim, blockdim](cp.asarray(S), cp.asarray(C), I, E, Z, dZ)
return I.get(), E.get(), Z.get(), dZ.get()
I, E, Z, dZ = iteration_numba_cuda(S, C) # use iteration_cupy_cuda or iteration_numba_cuda
D = np.zeros(C.shape, dtype=np.float64)
N = abs(Z) > 2 # exterior distance estimation
D[N] = np.log(abs(Z[N])) * abs(Z[N]) / abs(dZ[N])
plt.imshow(D ** 0.15, cmap=plt.cm.jet, origin="lower")
plt.savefig("Mandelbrot_deep_zoom.png", dpi=300)
print(
'\n'.join(
''.join(
' *'[(z:=0, c:=x/50+y/50j, [z:=z*z+c for _ in range(99)], abs(z))[-1]<2]
for x in range(-100,25)
)
for y in range(-50,50)
))

View file

@ -1,8 +1,5 @@
print(
'\n'.join(
''.join(
' *'[(z:=0, c:=x/50+y/50j, [z:=z*z+c for _ in range(99)], abs(z))[-1]<2]
for x in range(-100,25)
)
for y in range(-50,50)
))
from functools import reduce
def mandelbrot(x, y, c): return ' *'[abs(reduce(lambda z, _: z*z + c, range(99), 0)) < 2]
print('\n'.join(''.join(mandelbrot(x, y, x/50 + y/50j) for x in range(-100, 25)) for y in range(-50, 50)))

View file

@ -1,5 +0,0 @@
from functools import reduce
def mandelbrot(x, y, c): return ' *'[abs(reduce(lambda z, _: z*z + c, range(99), 0)) < 2]
print('\n'.join(''.join(mandelbrot(x, y, x/50 + y/50j) for x in range(-100, 25)) for y in range(-50, 50)))

View file

@ -14,14 +14,14 @@ def iteration(C):
S, T = np.zeros(C.shape), np.zeros(C.shape)
Z, dZ = np.zeros_like(C), np.zeros_like(C)
def iterate(C, S, T, Z, dZ):
def iterate1(C, S, T, Z, dZ):
S, T = S + np.exp(- abs(Z)), T + 1
Z, dZ = Z * Z + C, 2 * Z * dZ + 1
return S, T, Z, dZ
for i in range(n):
for i in range(0, n, 1):
M = abs(Z) < r
S[M], T[M], Z[M], dZ[M] = iterate(C[M], S[M], T[M], Z[M], dZ[M])
S[M], T[M], Z[M], dZ[M] = iterate1(C[M], S[M], T[M], Z[M], dZ[M])
return S, T, Z, dZ

View file

@ -17,14 +17,14 @@ def iteration(C):
S, T = np.zeros(C.shape), np.zeros(C.shape)
Z, dZ, ddZ = np.zeros_like(C), np.zeros_like(C), np.zeros_like(C)
def iterate(C, S, T, Z, dZ, ddZ):
def iterate1(C, S, T, Z, dZ, ddZ):
S, T = S + np.sin(density * np.angle(Z)), T + 1
Z, dZ, ddZ = Z * Z + C, 2 * Z * dZ + 1, 2 * (dZ * dZ + Z * ddZ)
return S, T, Z, dZ, ddZ
for i in range(n):
for i in range(0, n, 1):
M = abs(Z) < r
S[M], T[M], Z[M], dZ[M], ddZ[M] = iterate(C[M], S[M], T[M], Z[M], dZ[M], ddZ[M])
S[M], T[M], Z[M], dZ[M], ddZ[M] = iterate1(C[M], S[M], T[M], Z[M], dZ[M], ddZ[M])
return S, T, Z, dZ, ddZ

View file

@ -16,13 +16,17 @@ C = 8.0 * np.exp((A + B * 1j) * 1j) + (a + b * 1j)
def iteration(C):
Z, dZ = np.zeros_like(C), np.zeros_like(C)
def iterate(C, Z, dZ):
def iterate5(C, Z, dZ):
Z, dZ = Z * Z + C, 2 * Z * dZ + 1
Z, dZ = Z * Z + C, 2 * Z * dZ + 1
Z, dZ = Z * Z + C, 2 * Z * dZ + 1
Z, dZ = Z * Z + C, 2 * Z * dZ + 1
Z, dZ = Z * Z + C, 2 * Z * dZ + 1
return Z, dZ
for i in range(n):
for i in range(0, n, 5):
M = abs(Z) < r
Z[M], dZ[M] = iterate(C[M], Z[M], dZ[M])
Z[M], dZ[M] = iterate5(C[M], Z[M], dZ[M])
return Z, dZ

View file

@ -1,4 +1,5 @@
import numba
import numba.cuda as cuda
import numpy as np
import matplotlib.pyplot as plt
@ -12,10 +13,10 @@ n, r = 80000, 100000.0 # number of iterations and escape radius (r > 2)
a = dc.Decimal("-1.256827152259138864846434197797294538253477389787308085590211144291")
b = dc.Decimal(".37933802890364143684096784819544060002129071484943239316486643285025")
S = np.zeros(n+1, dtype=np.complex128)
S = np.zeros(n + 2, dtype=np.complex128) # 2 iterations are chained
u, v = dc.Decimal(0), dc.Decimal(0)
for i in range(n+1):
for i in range(n + 2):
S[i] = float(u) + float(v) * 1j
if u * u + v * v < r * r:
u, v = u * u - v * v + a, 2 * u * v + b
@ -41,25 +42,70 @@ def iteration_numba(S, C):
def abs2(z):
return z.real * z.real + z.imag * z.imag
def iterate(C, I, E, Z, dZ):
I, E = I + 1, (2 * S[I] + E) * E + C
Z, dZ = S[I] + E, 2 * Z * dZ + 1
return I, E, Z, dZ
def iterate2(delta, index, epsilon, z, dz):
index, epsilon = index + 1, (2 * S[index] + epsilon) * epsilon + delta
z, dz = S[index] + epsilon, 2 * z * dz + 1
index, epsilon = index + 1, (2 * S[index] + epsilon) * epsilon + delta
z, dz = S[index] + epsilon, 2 * z * dz + 1
return index, epsilon, z, dz
for i in range(n):
M = abs2(Z) < abs2(E) # rebase when z is closer to zero
I[M], E[M] = 0, Z[M] # reset the reference orbit
M = abs2(Z) < abs2(r)
I[M], E[M], Z[M], dZ[M] = iterate(C[M], I[M], E[M], Z[M], dZ[M])
for k in range(len(C)):
delta, index, epsilon, z, dz = C[k], I[k], E[k], Z[k], dZ[k]
for i in range(0, n, 2):
if abs2(z) < abs2(r):
if abs2(z) < abs2(epsilon):
index, epsilon = 0, z # reset the reference orbit
index, epsilon, z, dz = iterate2(delta, index, epsilon, z, dz)
else:
break
I[k], E[k], Z[k], dZ[k] = index, epsilon, z, dz
return I, E, Z, dZ
for j in numba.prange(d+1):
for j in numba.prange(C.shape[1]):
I[:, j], E[:, j], Z[:, j], dZ[:, j] = iteration(S, C[:, j])
return I, E, Z, dZ
I, E, Z, dZ = iteration_numba(S, C)
def iteration_numba_cuda(S, C):
I = np.zeros(C.shape, dtype=np.intp)
E, Z, dZ = np.zeros_like(C), np.zeros_like(C), np.zeros_like(C)
@cuda.jit()
def iteration(S, C, I, E, Z, dZ):
def abs2(z):
return z.real * z.real + z.imag * z.imag
def iterate2(delta, index, epsilon, z, dz):
index, epsilon = index + 1, (2 * S[index] + epsilon) * epsilon + delta
z, dz = S[index] + epsilon, 2 * z * dz + 1
index, epsilon = index + 1, (2 * S[index] + epsilon) * epsilon + delta
z, dz = S[index] + epsilon, 2 * z * dz + 1
return index, epsilon, z, dz
x, y = cuda.grid(2)
if x < C.shape[0] and y < C.shape[1]:
delta, index, epsilon, z, dz = C[x, y], I[x, y], E[x, y], Z[x, y], dZ[x, y]
for i in range(0, n, 2):
if abs2(z) < abs2(r):
if abs2(z) < abs2(epsilon):
index, epsilon = 0, z # reset the reference orbit
index, epsilon, z, dz = iterate2(delta, index, epsilon, z, dz)
else:
break
I[x, y], E[x, y], Z[x, y], dZ[x, y] = index, epsilon, z, dz
griddim, blockdim = ((C.shape[0] - 1) // 32 + 1, (C.shape[1] - 1) // 32 + 1), (32, 32)
I, E, Z, dZ = cuda.to_device(I), cuda.to_device(E), cuda.to_device(Z), cuda.to_device(dZ)
iteration[griddim, blockdim](cuda.to_device(S), cuda.to_device(C), I, E, Z, dZ)
return I.copy_to_host(), E.copy_to_host(), Z.copy_to_host(), dZ.copy_to_host()
I, E, Z, dZ = iteration_numba(S, C) # use iteration_numba or iteration_numba_cuda
D = np.zeros(C.shape, dtype=np.float64)
N = abs(Z) > 2 # exterior distance estimation

View file

@ -1,25 +1,21 @@
import jax
jax.config.update("jax_enable_x64", True) # faster on GPU P100 than on GPU T4
import numba
import numpy as np
import matplotlib.pyplot as plt
import cupy as cp
import jax.numpy as jnp
import decimal as dc # decimal floating point arithmetic with arbitrary precision
dc.getcontext().prec = 80 # set precision to 80 digits (about 256 bits)
d, h = 100, 2000 # pixel density (= image width) and image height
n, r = 100000, 100000.0 # number of iterations and escape radius (r > 2)
d, h = 1600, 1000 # pixel density (= image width) and image height
n, r = 80000, 100000.0 # number of iterations and escape radius (r > 2)
a = dc.Decimal("-1.256827152259138864846434197797294538253477389787308085590211144291")
b = dc.Decimal(".37933802890364143684096784819544060002129071484943239316486643285025")
S = np.zeros(n+1, dtype=np.complex128)
S = np.zeros(n + 100, dtype=np.complex128) # 100 iterations are chained
u, v = dc.Decimal(0), dc.Decimal(0)
for i in range(n+1):
for i in range(n + 100):
S[i] = float(u) + float(v) * 1j
if u * u + v * v < r * r:
u, v = u * u - v * v + a, 2 * u * v + b
@ -30,56 +26,91 @@ for i in range(n+1):
x = np.linspace(0, 2, num=d+1, dtype=np.float64)
y = np.linspace(0, 2 * h / d, num=h+1, dtype=np.float64)
A, B = np.meshgrid(x * np.pi, y * np.pi)
C = (- 8.0) * np.exp((A + B * 1j) * 1j)
A, B = np.meshgrid(x - 1, y - h / d)
C = 5.0e-35 * (A + B * 1j)
def iteration_cupy(S, C):
@numba.njit(parallel=True, fastmath=True)
def iteration_numba_bla(S, C):
I, J = np.zeros(C.shape, dtype=np.intp), np.zeros(C.shape, dtype=np.complex128)
E, Z, dZ = np.zeros_like(C), np.zeros_like(C), np.zeros_like(C)
def iteration(S, C):
I = cp.zeros(C.shape, dtype=np.intp)
E, Z, dZ = cp.zeros_like(C), cp.zeros_like(C), cp.zeros_like(C)
for i in range(n):
M = cp.absolute(Z) < cp.absolute(E) # rebase when z is closer to zero
I, E = cp.where(M, 0, I), cp.where(M, Z, E) # reset reference orbit
M = cp.absolute(Z) < r
I, E = cp.where(M, I + 1, I), cp.where(M, (2 * S[I] + E) * E + C, E)
Z, dZ = cp.where(M, S[I] + E, Z), cp.where(M, 2 * Z * dZ + 1, dZ)
return I, E, Z, dZ
I, E, Z, dZ = iteration(cp.asarray(S), cp.asarray(C))
return I.get(), E.get(), Z.get(), dZ.get()
def iteration_jax(S, C):
def iteration(S, C):
I = jnp.zeros(C.shape, dtype=np.intp)
E, Z, dZ = jnp.zeros_like(C), jnp.zeros_like(C), jnp.zeros_like(C)
def iteration(S, dS, R, A, B, C):
I, J = np.zeros(C.shape, dtype=np.intp), np.zeros(C.shape, dtype=np.complex128)
E, Z, dZ = np.zeros_like(C), np.zeros_like(C), np.zeros_like(C)
def abs2(z):
return z.real * z.real + z.imag * z.imag
def iterate(i, V):
I, E, Z, dZ = V
M = abs2(Z) < abs2(E) # rebase when z is closer to zero
I, E = jnp.where(M, 0, I), jnp.where(M, Z, E) # reset reference orbit
M = abs2(Z) < abs2(r)
I, E = jnp.where(M, I + 1, I), jnp.where(M, (2 * S[I] + E) * E + C, E)
Z, dZ = jnp.where(M, S[I] + E, Z), jnp.where(M, 2 * Z * dZ + 1, dZ)
return I, E, Z, dZ
def iterate2(delta, index, epsilon, z, dz):
index, epsilon = index + 1, (2 * S[index] + epsilon) * epsilon + delta
z, dz = S[index] + epsilon, 2 * z * dz + 1
index, epsilon = index + 1, (2 * S[index] + epsilon) * epsilon + delta
z, dz = S[index] + epsilon, 2 * z * dz + 1
return index, epsilon, z, dz
I, E, Z, dZ = jax.lax.fori_loop(0, n, iterate, (I, E, Z, dZ), unroll=10)
return I, E, Z, dZ
def skip100(delta, index, e, z, dz):
de = dz - dS[index] # no catastrophic cancellation (don't try that with e)
# for l in range(100): # skip 100 iterations (using linear approximations)
# index, e, de = index + 1, 2 * S[index] * e + delta, 2 * S[index] * de
index, e, de = index + 100, A[index] * e + B[index] * delta, A[index] * de
z, dz = S[index] + e, dS[index] + de
return index, e, z, dz
I, E, Z, dZ = iteration(jnp.asarray(S), jnp.asarray(C))
return np.asarray(I), np.asarray(E), np.asarray(Z), np.asarray(dZ)
for k in range(len(C)):
delta, index, epsilon, z, dz = C[k], I[k], E[k], Z[k], dZ[k]
I, E, Z, dZ = iteration_jax(S, C) # use iteration_cupy or iteration_jax
D = np.zeros(C.shape, dtype=np.float64)
i, j = 0, 0
while i + j < n:
if abs2(z) < abs2(r):
if abs2(epsilon) < abs2(1e-10 * R[index]):
index, epsilon, z, dz = skip100(delta, index, epsilon, z, dz)
j = j + 100
else:
if abs2(z) < abs2(epsilon):
index, epsilon = 0, z # reset the reference orbit
index, epsilon, z, dz = iterate2(delta, index, epsilon, z, dz)
i = i + 2
else:
break
I[k], E[k], Z[k], dZ[k], J[k] = index, epsilon, z, dz, complex(i + j, j)
return I, E, Z, dZ, J
A, B = np.ones(n, dtype=np.complex128), np.zeros(n, dtype=np.complex128)
R, aS = np.full(n, 2, dtype=np.float64), np.where(np.abs(S) < 2, np.abs(S), 0)
dS = np.zeros(n + 100, dtype=np.complex128)
for i in range(1, n + 100): # derivation of the series (accuracy is not required)
dS[i] = 2 * S[i - 1] * dS[i - 1] + 1
for i in numba.prange(n): # coefficients und radii for the bilinear approximation
for l in range(100):
A[i], B[i] = 2 * S[i + l] * A[i], 2 * S[i + l] * B[i] + 1
R[i] = min(R[i], aS[i + l]) # validity radii and skip barriers (zeros)
for i in numba.prange(C.shape[0]):
I[i, :], E[i, :], Z[i, :], dZ[i, :], J[i, :] = iteration(S, dS, R, A, B, C[i, :])
return I, E, Z, dZ, J
I, E, Z, dZ, J = iteration_numba_bla(S, C)
D, T = np.zeros(C.shape, dtype=np.float64), J.real.copy()
skipped = J.imag.sum() / J.real.sum()
print("%.1f%% of all iterations were skipped." % (skipped * 100))
N = abs(Z) > 2 # exterior distance estimation
D[N] = np.log(abs(Z[N])) * abs(Z[N]) / abs(dZ[N])
plt.imshow(D.T ** 0.015, cmap=plt.cm.gist_ncar, origin="lower")
plt.savefig("Mercator_Mandelbrot_deep_map.png", dpi=200)
plt.imshow(D ** 0.15, cmap=plt.cm.turbo, origin="lower")
plt.savefig("Mandelbrot_deep_zoom.png", dpi=200)
N = abs(Z) >= r # normalized iteration count
T[N] = T[N] - np.log2(np.log(abs(Z[N])) / np.log(r))
T = np.minimum(T, n) # truncation
T = (T - T.min()) / (T.max() - T.min()) # scaling
plt.imshow(T ** 0.2, cmap=plt.cm.jet, origin="lower")
plt.savefig("Mandelbrot_deep_time.png", dpi=200)

View file

@ -1,16 +1,13 @@
#install.packages("caTools") # install external package (if missing)
library(caTools) # external package providing write.gif function
jet.colors <- colorRampPalette(c("red", "blue", "#007FFF", "cyan", "#7FFF7F",
"yellow", "#FF7F00", "red", "#7F0000"))
dx <- 800 # define width
dy <- 600 # define height
C <- complex(real = rep(seq(-2.5, 1.5, length.out = dx), each = dy),
imag = rep(seq(-1.5, 1.5, length.out = dy), dx))
C <- matrix(C, dy, dx) # reshape as square matrix of complex numbers
Z <- 0 # initialize Z to zero
X <- array(0, c(dy, dx, 20)) # initialize output 3D array
for (k in 1:20) { # loop with 20 iterations
Z <- Z^2 + C # the central difference equation
X[, , k] <- exp(-abs(Z)) # capture results
dx=800; dy=600 # define grid size
C = complex(real=rep(seq(-2.2, 1.0, length.out=dx), each=dy),
imag=rep(seq(-1.2, 1.2, length.out=dy), dx))
C = matrix(C, dy, dx) # convert from vector to matrix
Z = 0 # initialize Z to zero
X = array(0, c(dy, dx, 20)) # allocate memory for all the frames
for (k in 1:20) { # perform 20 iterations
Z = Z^2+C # the main equation
X[, , k] = exp(-abs(Z)) # store magnitude of the complex number
}
write.gif(X, "Mandelbrot.gif", col = jet.colors, delay = 100)
library(caTools) # load library with write.gif function
jetColors = colorRampPalette(c("#00007F", "blue", "#007FFF", "cyan", "#7FFF7F", "yellow", "#FF7F00", "red", "#7F0000"))
write.gif(X, "Mandelbrot.gif", col=jetColors, delay=100, transparent=0)

View file

@ -1,263 +0,0 @@
option explicit
' Raster graphics class in VBSCRIPT by Antoni Gual
'--------------------------------------------
' An array keeps the image allowing to set pixels, draw lines and boxes in it.
' at class destroy a bmp file is saved to disk and the default viewer is called
' The class can work with 8 and 24 bit bmp. With 8 bit uses a built-in palette or can import a custom one
'Declaration :
' Set MyObj = (New ImgClass)(name,width,height, orient,bits_per_pixel,palette_array)
' name:path and name of the file created
' width, height of the canvas
' orient is the way the coord increases, 1 to 4 think of the 4 cuadrants of the caterian plane
' 1 X:l>r Y:b>t 2 X:r>l Y:b>t 3 X:r>l Y:t>b 4 X:l>r Y:t>b
' bits_per_pixel can bs only 8 and 24
' palette array only to substitute the default palette for 8 bits, else put a 0
' it sets the origin at the corner of the image (bottom left if orient=1)
Class ImgClass
Private ImgL,ImgH,ImgDepth,bkclr,loc,tt
private xmini,xmaxi,ymini,ymaxi,dirx,diry
public ImgArray() 'rgb in 24 bit mode, indexes to palette in 8 bits
private filename
private Palette,szpal
Public Property Let depth (x)
if depth=8 or depth =24 then
Imgdepth=depth
else
Imgdepth=8
end if
bytepix=imgdepth/8
end property
Public Property Let Pixel (x,y,color)
If (x>=ImgL) or x<0 then exit property
if y>=ImgH or y<0 then exit property
ImgArray(x,y)=Color
End Property
Public Property Get Pixel (x,y)
If (x<ImgL) And (x>=0) And (y<ImgH) And (y>=0) Then
Pixel=ImgArray(x,y)
End If
End Property
Public Property Get ImgWidth ()
ImgWidth=ImgL-1
End Property
Public Property Get ImgHeight ()
ImgHeight=ImgH-1
End Property
'constructor (fn,w*2,h*2,32,0,0)
Public Default Function Init(name,w,h,orient,dep,bkg,mipal)
'offx, offy posicion de 0,0. si ofx+ , x se incrementa de izq a der, si offy+ y se incrementa de abajo arriba
dim i,j
ImgL=w
ImgH=h
tt=timer
set0 0,0 'origin blc positive up and right
redim imgArray(ImgL-1,ImgH-1)
bkclr=bkg
if bkg<>0 then
for i=0 to ImgL-1
for j=0 to ImgH-1
imgarray(i,j)=bkg
next
next
end if
Select Case orient
Case 1: dirx=1 : diry=1
Case 2: dirx=-1 : diry=1
Case 3: dirx=-1 : diry=-1
Case 4: dirx=1 : diry=-1
End select
filename=name
ImgDepth =dep
'load user palette if provided
if imgdepth=8 then
loadpal(mipal)
end if
set init=me
end function
private sub loadpal(mipale)
if isarray(mipale) Then
palette=mipale
szpal=UBound(mipale)+1
Else
szpal=256
'Default palette recycled from ATARI
End if
End Sub
public sub set0 (x0,y0) 'origin can be changed during drawing
if x0<0 or x0>=imgl or y0<0 or y0>imgh then err.raise 9
xmini=-x0
ymini=-y0
xmaxi=xmini+imgl-1
ymaxi=ymini+imgh-1
end sub
Private Sub Class_Terminate
if err <>0 then wscript.echo "Error " & err.number
wscript.echo "writing bmp to file"
savebmp
wscript.echo "opening " & filename
CreateObject("Shell.Application").ShellExecute filename
wscript.echo timer-tt & " seconds"
End Sub
'writes a 32bit integr value as binary to an utf16 string
function long2wstr( x) 'falta muy poco!!!
dim k1,k2,x1
k1= (x and &hffff&)' or (&H8000& And ((X And &h8000&)<>0)))
k2=((X And &h7fffffff&) \ &h10000&) Or (&H8000& And (x<0))
long2wstr=chrw(k1) & chrw(k2)
end function
function int2wstr(x)
int2wstr=ChrW((x and &h7fff) or (&H8000 And (X<0)))
End Function
Public Sub SaveBMP
'Save the picture to a bmp file
Dim s,ostream, x,y,loc
const hdrs=54 '14+40
dim bms:bms=ImgH* 4*(((ImgL*imgdepth\8)+3)\4) 'bitmap size including padding
dim palsize:if (imgdepth=8) then palsize=szpal*4 else palsize=0
with CreateObject("ADODB.Stream") 'auxiliary ostream, it creates an UNICODE with bom stream in memory
.Charset = "UTF-16LE" 'o "UTF16-BE"
.Type = 2' adTypeText
.open
'build a header
'bmp header: VBSCript does'nt have records nor writes binary values to files, so we use strings of unicode chars!!
'BMP header
.writetext ChrW(&h4d42) ' 0 "BM" 4d42
.writetext long2wstr(hdrs+palsize+bms) ' 2 fiesize
.writetext long2wstr(0) ' 6 reserved
.writetext long2wstr (hdrs+palsize) '10 image offset
'InfoHeader
.writetext long2wstr(40) '14 infoheader size
.writetext long2wstr(Imgl) '18 image length
.writetext long2wstr(imgh) '22 image width
.writetext int2wstr(1) '26 planes
.writetext int2wstr(imgdepth) '28 clr depth (bpp)
.writetext long2wstr(&H0) '30 compression used 0= NOCOMPR
.writetext long2wstr(bms) '34 imgsize
.writetext long2wstr(&Hc4e) '38 bpp hor
.writetext long2wstr(&hc43) '42 bpp vert
.writetext long2wstr(szpal) '46 colors in palette
.writetext long2wstr(&H0) '50 important clrs 0=all
'write bitmap
'precalc data for orientation
Dim x1,x2,y1,y2
If dirx=-1 Then x1=ImgL-1 :x2=0 Else x1=0:x2=ImgL-1
If diry=-1 Then y1=ImgH-1 :y2=0 Else y1=0:y2=ImgH-1
Select Case imgdepth
Case 32
For y=y1 To y2 step diry
For x=x1 To x2 Step dirx
'writelong fic, Pixel(x,y)
.writetext long2wstr(Imgarray(x,y))
Next
Next
Case 8
'palette
For x=0 to szpal-1
.writetext long2wstr(palette(x)) '52
Next
'image
dim pad:pad=ImgL mod 4
For y=y1 to y2 step diry
For x=x1 To x2 step dirx*2
.writetext chrw((ImgArray(x,y) and 255)+ &h100& *(ImgArray(x+dirx,y) and 255))
Next
'line padding
if pad and 1 then .writetext chrw(ImgArray(x2,y))
if pad >1 then .writetext chrw(0)
Next
Case Else
WScript.Echo "ColorDepth not supported : " & ImgDepth & " bits"
End Select
'use a second stream to save to file starting past the BOM the first ADODB.Stream has added
Dim outf:Set outf= CreateObject("ADODB.Stream")
outf.Type = 1 ' adTypeBinary
outf.Open
.position=2 'remove bom (1 wchar)
.CopyTo outf
.close
outf.savetofile filename,2 'adSaveCreateOverWrite
outf.close
end with
End Sub
End Class
function mandelpx(x0,y0,maxit)
dim x,y,xt,i,x2,y2
i=0:x2=0:y2=0
Do While i< maxit
i=i+1
xt=x2-y2+x0
y=2*x*y+y0
x=xt
x2=x*x:y2=y*y
If (x2+y2)>=4 Then Exit do
loop
if i=maxit then
mandelpx=0
else
mandelpx = i
end if
end function
Sub domandel(x1,x2,y1,y2)
Dim i,ii,j,jj,pix,xi,yi,ym
ym=X.ImgHeight\2
'get increments in the mandel plane
xi=Abs((x1-x2)/X.ImgWidth)
yi=Abs((y2-0)/(X.ImgHeight\2))
j=0
For jj=0. To y2 Step yi
i=0
For ii=x1 To x2 Step xi
pix=mandelpx(ii,jj,256)
'use simmetry
X.imgarray(i,ym-j)=pix
X.imgarray(i,ym+j)=pix
i=i+1
Next
j=j+1
next
End Sub
'main------------------------------------
Dim i,x
'custom palette
dim pp(255)
for i=1 to 255
pp(i)=rgb(0,0,255*(i/255)^.25) 'VBS' RGB function is for the web, it's bgr for Windows BMP !!
next
dim fn:fn=CreateObject("Scripting.FileSystemObject").GetSpecialFolder(2)& "\mandel.bmp"
Set X = (New ImgClass)(fn,580,480,1,8,0,pp)
domandel -2.,1.,-1.2,1.2
Set X = Nothing