Skip to main content

Overview

Fract’ol uses three main structures defined in fractol.h:
  • t_complex: Represents complex numbers
  • t_img: Manages MLX image buffer data
  • t_fractol: Central state container for the entire application

t_complex

Represents a complex number in Cartesian form (real + imaginary components).
fractol.h:46-50
typedef struct s_complex
{
    double x;
    double y;
} t_complex;

Fields

x
double
Real component of the complex number. In standard mathematical notation, this represents the real part of a+bia + bi.
  • For screen coordinates: horizontal position mapped to complex plane (typically -2 to +2)
  • For fractal calculations: the aa in a+bia + bi
y
double
Imaginary component of the complex number. Represents the coefficient of ii in a+bia + bi.
  • For screen coordinates: vertical position mapped to complex plane (typically -2 to +2)
  • For fractal calculations: the bb in a+bia + bi

Usage

t_complex z;
z.x = (map(x, -2, +2, WIDTH) * fractol->zoom) + fractol->shift_x;
z.y = (map(y, +2, -2, HEIGHT) * fractol->zoom) + fractol->shift_y;
// z now represents the complex number at screen position (x, y)

Design Notes

The structure uses x and y instead of real and imag to emphasize the geometric interpretation:
  • x = horizontal axis (real axis)
  • y = vertical axis (imaginary axis)
This naming aligns with the coordinate mapping from screen pixels to the complex plane.

t_img

Contains MiniLibX image buffer data for direct pixel manipulation.
fractol.h:52-59
typedef struct s_img
{
    void  *img_ptr;
    char  *pixel_ptr;
    int   bpp;
    int   line_length;
    int   endian;
} t_img;

Fields

img_ptr
void*
MLX image pointer returned by mlx_new_image().
  • Opaque handle to the image buffer
  • Used for operations like mlx_put_image_to_window() and mlx_destroy_image()
  • Must not be freed directly (use mlx_destroy_image())
pixel_ptr
char*
Direct memory address of the pixel data array, obtained from mlx_get_data_addr().
  • Points to raw pixel buffer in memory
  • Allows direct byte-level pixel manipulation
  • Used to calculate offset: (y * line_length) + (x * (bpp / 8))
bpp
int
Bits per pixel - the number of bits used to store each pixel’s color.
  • Typical value: 32 (4 bytes per pixel for ARGB)
  • Divide by 8 to get bytes per pixel
  • Populated by mlx_get_data_addr()
line_length
int
Line length in bytes - the number of bytes per row in the image buffer.
  • May include padding for memory alignment
  • Not necessarily equal to width * (bpp / 8)
  • Critical for calculating pixel offset: y * line_length
endian
int
Endianness of pixel data - byte order for multi-byte color values.
  • 0 = little-endian (least significant byte first)
  • 1 = big-endian (most significant byte first)
  • Populated by mlx_get_data_addr()

Initialization

From fractol_init.c:53-63:
fractol->img.img_ptr = mlx_new_image(fractol->mlx_connection, WIDTH, HEIGHT);
if (fractol->img.img_ptr == NULL)
{
    // cleanup and error handling
}
fractol->img.pixel_ptr = mlx_get_data_addr(fractol->img.img_ptr,
        &fractol->img.bpp, &fractol->img.line_length, &fractol->img.endian);

Pixel Manipulation

From fractol_render.c:15-21:
static void my_pixel_put(int x, int y, t_img *img, int color)
{
    int offset;

    offset = (y * img->line_length) + (x * (img->bpp / 8));
    *(unsigned int *)(img->pixel_ptr + offset) = color;
}

t_fractol

The central data structure containing all application state.
fractol.h:61-74
typedef struct s_fractol
{
    char   *name;
    void   *mlx_connection;
    void   *mlx_window;
    t_img  img;
    double escape_value;
    int    iterations_definition;
    double shift_x;
    double shift_y;
    double zoom;
    double julia_x;
    double julia_y;
} t_fractol;

Fields

Fractal Configuration

name
char*
Fractal type identifier - points to the command-line argument string.
  • Value: "Mandelbrot" or "Julia"
  • Set in main.c:22 from argv[1]
  • Used to determine rendering algorithm in mandel_vs_julia()
  • Not allocated - points to argv, do not free
julia_x
double
Real component of the Julia set constant cc.
  • Only used when name == "Julia"
  • Set from command-line: ./fractol Julia 0.285 0.01
  • Parsed in main.c:25 via atoi_plus(argv[2])
  • Common values: -0.8 to 0.8
julia_y
double
Imaginary component of the Julia set constant cc.
  • Only used when name == "Julia"
  • Parsed in main.c:26 via atoi_plus(argv[3])
  • Common values: -0.5 to 0.5
  • Together with julia_x, defines which Julia set to render

MLX Resources

mlx_connection
void*
MLX connection handle to the X Window System.
  • Initialized by mlx_init() in fractol_init.c:42
  • Required for all MLX function calls
  • Must be freed with free() after mlx_destroy_display()
  • NULL indicates initialization failure
mlx_window
void*
MLX window pointer for the display window.
  • Created by mlx_new_window() with dimensions 2000×1500
  • Window title set to fractol->name
  • Destroyed with mlx_destroy_window() on exit
img
t_img
Image buffer structure containing pixel data.
  • See t_img documentation above
  • Embedded structure (not a pointer)
  • Initialized in fractol_init() after window creation

Rendering Parameters

escape_value
double
Escape threshold for fractal iteration - squared magnitude limit.
  • Default: 4.0 (set in data_init())
  • Represents r2r^2 where r=2r = 2 is the escape radius
  • Point escapes when z2=x2+y2>|z|^2 = x^2 + y^2 > escape_value
  • Using squared value avoids expensive sqrt() calls
iterations_definition
int
Maximum iteration count before considering a point in the set.
  • Default: 30 (set in data_init())
  • Increased by 5 when + key pressed
  • Decreased by 5 when - key pressed
  • Higher values = more detail but slower rendering
  • Also used as range for color gradient mapping

View Transformation

shift_x
double
Horizontal pan offset in complex plane coordinates.
  • Default: 0.0 (centered)
  • Decreased by 0.5 * zoom when Left/A pressed
  • Increased by 0.5 * zoom when Right/D pressed
  • Added to mapped x-coordinate: z.x = (map(...) * zoom) + shift_x
shift_y
double
Vertical pan offset in complex plane coordinates.
  • Default: 0.0 (centered)
  • Increased by 0.5 * zoom when Up/W pressed (note: inverted)
  • Decreased by 0.5 * zoom when Down/S pressed
  • Added to mapped y-coordinate: z.y = (map(...) * zoom) + shift_y
zoom
double
Zoom level multiplier - scales the view of the complex plane.
  • Default: 1.0 (no magnification)
  • Multiplied by 0.95 on scroll up (zoom in)
  • Multiplied by 1.05 on scroll down (zoom out)
  • Lower values = more zoomed in (smaller zoom multiplier)
  • Applied to coordinates: z.x = map(...) * zoom

Initialization Sequence

From main.c:17-30 and fractol_init.c:40-66:
main.c
t_fractol fractol;
fractol.name = argv[1];
if (!ft_strncmp(fractol.name, "Julia"))
{
    fractol.julia_x = atoi_plus(argv[2]);
    fractol.julia_y = atoi_plus(argv[3]);
}
fractol_init(&fractol);
fractol_init.c
void fractol_init(t_fractol *fractol)
{
    fractol->mlx_connection = mlx_init();
    fractol->mlx_window = mlx_new_window(fractol->mlx_connection, WIDTH, HEIGHT, fractol->name);
    fractol->img.img_ptr = mlx_new_image(fractol->mlx_connection, WIDTH, HEIGHT);
    fractol->img.pixel_ptr = mlx_get_data_addr(/* ... */);
    events_init(fractol);
    data_init(fractol);
}

Usage Patterns

// Command: ./fractol Mandelbrot
t_fractol fractol;
fractol.name = "Mandelbrot";
fractol_init(&fractol);
// After init:
// - julia_x, julia_y: undefined (not used)
// - escape_value: 4.0
// - iterations_definition: 30
// - shift_x, shift_y: 0.0
// - zoom: 1.0

Memory Layout

Size estimate (64-bit system):
char*  name              8 bytes
void*  mlx_connection    8 bytes
void*  mlx_window        8 bytes
t_img  img              32 bytes (5 fields)
double escape_value      8 bytes
int    iterations_def    4 bytes
double shift_x           8 bytes
double shift_y           8 bytes
double zoom              8 bytes
double julia_x           8 bytes
double julia_y           8 bytes
─────────────────────────────────
Total: ~108 bytes (plus padding)
The structure is stack-allocated in main() and passed by pointer to all functions. This avoids heap allocation overhead while maintaining single-source-of-truth for application state.

Utility Functions

These helper functions from string_utils.c support argument parsing and string comparison.

atoi_plus()

Enhanced string-to-double converter that handles floating-point numbers with optional sign.
fractol.h:77
double atoi_plus(char *s);
s
char*
required
String to parse - must contain valid numeric characters, optional sign (+/-), and optional decimal point

Returns

result
double
Parsed floating-point value with sign applied

Implementation

From string_utils.c:15-41:
double atoi_plus(char *s)
{
    long   integer_part;
    double fractional_part;
    double pow;
    int    sign;

    integer_part = 0;
    fractional_part = 0;
    sign = +1;
    pow = 1;
    while ((*s >= 9 && *s <= 13) || 32 == *s)
        ++s;
    while ('+' == *s || '-' == *s)
        if ('-' == *s++)
            sign = -sign;
    while (*s != '.' && *s)
        integer_part = (integer_part * 10) + (*s++ - 48);
    if ('.' == *s)
        ++s;
    while (*s)
    {
        pow /= 10;
        fractional_part = fractional_part + (*s++ - 48) * pow;
    }
    return ((integer_part + fractional_part) * sign);
}

Behavior

  1. Whitespace skipping: Handles spaces and control characters (ASCII 9-13, 32)
  2. Sign parsing: Processes multiple +/- characters (each - toggles sign)
  3. Integer part: Builds integer by multiplying by 10 and adding each digit
  4. Decimal point: Detects and skips ’.’
  5. Fractional part: Accumulates decimal places with decreasing powers of 10
  6. Sign application: Multiplies result by final sign

Usage in main()

From main.c:25-26:
if (!ft_strncmp(fractol.name, "Julia"))
{
    fractol.julia_x = atoi_plus(argv[2]);
    fractol.julia_y = atoi_plus(argv[3]);
}

Examples

atoi_plus("0.285")     → 0.285
atoi_plus("-0.8")      → -0.8
atoi_plus("+1.5")      → 1.5
atoi_plus("  -0.5  ")  → -0.5
atoi_plus("--1.0")     → 1.0   (double negative)
atoi_plus("3.14159")   → 3.14159
No error checking for invalid input. Non-numeric characters are treated as digit values minus 48 (ASCII ‘0’). Empty strings return 0.

ft_strncmp()

Simplified string comparison function that compares two strings until they differ or one ends.
fractol.h:76
int ft_strncmp(char *s1, char *s2);
s1
char*
required
First string to compare (can be NULL)
s2
char*
required
Second string to compare (can be NULL)

Returns

result
int
  • 0 if strings are identical or both NULL
  • Positive if s1 > s2 at first differing character
  • Negative if s1 < s2 at first differing character

Implementation

From string_utils.c:43-53:
int ft_strncmp(char *s1, char *s2)
{
    if (s1 == NULL || s2 == NULL)
        return (0);
    while (*s1 == *s2 && *s1 != '\0')
    {
        s1++;
        s2++;
    }
    return (*s1 - *s2);
}

Behavior

  1. NULL safety: Returns 0 if either string is NULL
  2. Character-by-character: Compares until mismatch or null terminator
  3. ASCII difference: Returns difference of character values at mismatch point
Unlike standard strncmp(), this compares entire strings without a length limit. The name is a 42 School convention rather than standard library compatibility.

Usage in Fractal Type Detection

From main.c:19-20:
if ((argc == 2 && !ft_strncmp(argv[1], "Mandelbrot"))
    || (argc == 4 && !ft_strncmp(argv[1], "Julia")))
From fractol_render.c:25:
if (!ft_strncmp(fractol->name, "Julia"))
{
    c->x = fractol->julia_x;
    c->y = fractol->julia_y;
}

Examples

ft_strncmp("Julia", "Julia")       → 0  (equal)
ft_strncmp("Mandelbrot", "Julia")  → 3  ('M' - 'J')
ft_strncmp("abc", "abd")           → -1 ('c' - 'd')
ft_strncmp(NULL, "test")           → 0  (NULL safety)
ft_strncmp("hello", "hello!")      → -33 ('\0' - '!')
In the codebase, this is always used with negation: !ft_strncmp(s1, s2) to check for equality, similar to how strcmp() == 0 checks equality in standard C.

Build docs developers (and LLMs) love