' Mandelbrot Set Generator for jdBasic (Vectorized & Optimized Drawing)
' --------------------------------------------------------------------
' This program calculates and draws the Mandelbrot fractal using
' APL-style array operations and a high-performance raw plotting procedure.

' --- 1. Configuration and Setup ---
SCREEN_W = 1920
 SCREEN_H = 1080
MAX_ITERATIONS = 50 ' Increase for more detail, but slower rendering
CALC_W = 192
CALC_H = 108
DX = SCREEN_W / CALC_W
DY = SCREEN_H / CALC_H
' Define the view of the complex plane to render
X_MIN = -2.0
X_MAX = 1.0
Y_MIN = -1.0
Y_MAX = 1.0

' A more zoomed-in view to see more detail
'X_MIN = -0.75
'X_MAX = -0.74
'Y_MIN = 0.1
'Y_MAX = 0.11

' --- 2. Initialize Graphics ---
PRINT "Initializing graphics screen..."
SCREEN SCREEN_W, SCREEN_H, "Mandelbrot Set in jdBasic (Vectorized)"
CLS 0, 0, 0 ' Clear screen to black

' --- 3. Vectorized Coordinate Setup ---
PRINT "Creating coordinate matrices..."

' Create 1D vectors for all X and Y coordinates on the screen
PX_VEC = (IOTA(CALC_W) - 1) / (CALC_W - 1)
PY_VEC = (IOTA(CALC_H) - 1) / (CALC_H - 1)

' Use OUTER to expand the 1D vectors into 2D coordinate matrices
C_REAL = OUTER(PY_VEC*0, PX_VEC, "+") * (X_MAX - X_MIN) + X_MIN
C_IMAG = OUTER(PY_VEC, PX_VEC*0, "+") * (Y_MAX - Y_MIN) + Y_MIN


' --- 4. Vectorized Iteration ---
PRINT "Calculating Mandelbrot set with matrix operations..."

' Initialize Z and iteration-count matrices
Z_REAL = RESHAPE([0], [CALC_H, CALC_W])
Z_IMAG = RESHAPE([0], [CALC_H, CALC_W])
ITERATIONS = RESHAPE([0], [CALC_H, CALC_W])

' This loop replaces the inner DO/WHILE. It iterates for all points at once.
FOR I = 1 TO MAX_ITERATIONS
  ' Create a boolean mask of points that are still within the escape radius
  STILL_CALCULATING_MASK = (Z_REAL^2 + Z_IMAG^2) <= 4

  ' If all points have escaped, we can stop early
  IF NOT ANY(STILL_CALCULATING_MASK) THEN EXITFOR

  ' Increment iteration count only for points still being calculated
  ITERATIONS = ITERATIONS + STILL_CALCULATING_MASK

  ' Calculate z^2 + c for all points
  Z_REAL_NEW = (Z_REAL^2 - Z_IMAG^2) + C_REAL
  Z_IMAG_NEW = (2 * Z_REAL * Z_IMAG) + C_IMAG

  ' Update Z values only for the points still inside the mask
  Z_REAL = Z_REAL_NEW * STILL_CALCULATING_MASK + Z_REAL * (1 - STILL_CALCULATING_MASK)
  Z_IMAG = Z_IMAG_NEW * STILL_CALCULATING_MASK + Z_IMAG * (1 - STILL_CALCULATING_MASK)
  PRINT "Calculating iteration: "; I
NEXT I


' --- 5. Vectorized Coloring ---
PRINT "Calculating final color matrix..."

' Create a mask for points inside the set (those that reached max iterations)
INSIDE_SET_MASK = (ITERATIONS = MAX_ITERATIONS)

' Calculate colors for points outside the set based on escape time
R = (ITERATIONS * 8) MOD 255
G = (ITERATIONS * 5) MOD 255
B = (ITERATIONS * 12) MOD 255

' Apply the "inside set" mask to make those pixels black
R = R * (1 - INSIDE_SET_MASK)
G = G * (1 - INSIDE_SET_MASK)
B = B * (1 - INSIDE_SET_MASK)

' Pack the R, G, and B matrices into a single integer color matrix
' The formula is equivalent to (R << 16) | (G << 8) | B
COLOR_MATRIX = R * 65536 + G * 256 + B


' --- 6. Draw the Final Image ---
PRINT "Drawing final image with PLOTRAW..."

' Call the new high-performance procedure to draw the entire matrix at once
PLOTRAW 0, 0, COLOR_MATRIX, DX, DY

' Push the completed drawing to the screen
SCREENFLIP

PRINT "Calculation complete. Press any key to exit."
do
 a$ = inkey$()
 sleep 10
loop until a$ > ""

