Skip to content

Instantly share code, notes, and snippets.

@sleibrock
Last active January 14, 2022 22:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sleibrock/7f6167d96c104bc0ac26662f819ec2e4 to your computer and use it in GitHub Desktop.
Save sleibrock/7f6167d96c104bc0ac26662f819ec2e4 to your computer and use it in GitHub Desktop.
test.zig
// tester.zig - a basic mandelbrot prototype
const std = @import("std");
const io = std.io;
const os = std.os;
const fs = std.fs;
const fmt = std.fmt;
const math = std.math;
/// A Complex<T> data type to use
/// Can work with signed ints or Floats
/// Most likely will end up only being used with f64/f128
fn Complex(comptime T: type) type {
return struct {
real: T = 0,
imag: T = 0,
const Self = @This();
fn init(x: T, y: T) Self {
return Self{ .real = x, .imag = y };
}
fn add(self: Self, other: *Self) Self {
return Self{
.real = self.real + other.real,
.imag = self.imag + other.imag,
};
}
fn adds(self: *Self, other: *Self) void {
self.real += other.real;
self.imag += other.imag;
}
fn sub(self: Self, other: *Self) Self {
return Self{
.real = self.real - other.real,
.imag = self.imag - other.imag,
};
}
fn subs(self: *Self, other: *Self) void {
self.real -= other.real;
self.imag -= other.imag;
}
fn mul(self: Self, other: *Self) Self {
return Self{
.real = (self.real * other.real) - (self.imag * other.imag),
.imag = (self.imag * other.real) + (self.real * other.imag),
};
}
fn muls(self: *Self, other: *Self) void {
const r = (self.real * other.real) - (self.imag * other.imag);
self.imag = (self.imag * other.real) + (self.real * other.imag);
self.real = r;
}
fn div(self: Self, other: *Self) Self {
const d = (other.real * other.real) + (other.imag * other.imag);
return Self{
.real = ((self.real * other.real) + (self.imag * other.imag)) / d,
.imag = ((self.imag * other.real) - (self.real * other.imag)) / d,
};
}
fn divs(self: *Self, other: *Self) !void {
const d = (other.real * other.real) + (other.imag * other.imag);
const r = ((self.real * other.real) + (self.imag * other.imag)) / d;
self.imag = ((self.imag * other.real) - (self.real * other.imag)) / d;
self.real = r;
}
fn negate(self: Self) Self {
return Self{
.real = -self.real,
.imag = -self.imag,
};
}
fn conjugate(self: Self) Self {
return Self{
.real = self.real,
.imag = -self.imag,
};
}
fn length2(self: Self) T {
return (self.real * self.real) + (self.imag * self.imag);
}
};
}
const FTYPE = f64;
const Cbig = Complex(FTYPE);
//const Cbig = math.Complex(f128);
pub fn clear_buffer(bufslice: []u8) void {
var i: usize = 0;
while (i < bufslice.len) : (i += 1) {
bufslice[i] = 0;
}
return;
}
pub fn iter(Z: *Cbig, C: *Cbig) u8 {
var i: u8 = 0;
while (i < 255 and (Z.length2() < 4.0)) : (i += 1) {
Z.muls(Z);
Z.adds(C);
}
return i;
}
pub fn main() !void {
const width: usize = 640;
const height: usize = 480;
const width_f: FTYPE = @intToFloat(FTYPE, width);
const height_f: FTYPE = @intToFloat(FTYPE, height);
var y: usize = 0;
var x: usize = 0;
const r_min: FTYPE = -1.67;
const r_max: FTYPE = 0.80;
const i_min: FTYPE = -1.12;
const i_max: FTYPE = 1.12;
// create
var C = Cbig.init(r_min, i_min);
var Z = Cbig.init(0, 0);
var i: u8 = 0;
var bi: usize = 0;
const bufsize: usize = 900;
var buffer: [bufsize]u8 = undefined;
var r_increment = Cbig.init((math.fabs(r_min) + math.fabs(r_max)) / (width_f), 0);
var i_increment = Cbig.init(0, (math.fabs(i_min) + math.fabs(i_max)) / (height_f));
// create a file and open up a writer stream
var fi = try fs.cwd().openFileZ("test.ppm", .{ .write = true });
var writer = fi.writer();
defer fi.close();
// write the headers
try writer.print("P6\n", .{});
try writer.print("#Real <>, Imag <>\n", .{});
try writer.print("640 480\n", .{});
try writer.print("255\n", .{});
// main loop for rendering
while (y < height) : (y += 1) {
while (x < width) : (x += 1) {
Z.real = 0;
Z.imag = 0;
i = iter(&Z, &C);
C.adds(&r_increment);
// write to buffer using a buffer index instead of x
buffer[bi] = i;
buffer[bi + 1] = i;
buffer[bi + 2] = i;
bi += 3;
// do a buffer check to see if we went past our maximum
// if we go past, write and clear
if (bi >= bufsize) {
try writer.print("{s}", .{buffer[0..bufsize]});
bi = 0;
}
}
x = 0;
C.real = r_min;
C.adds(&i_increment);
}
// if we have remaining buffer values, write and clear
if (bi > 0) {
try writer.print("{s}", .{buffer[0..bi]});
}
// done
}
// end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment