Last active
January 14, 2022 22:45
-
-
Save sleibrock/7f6167d96c104bc0ac26662f819ec2e4 to your computer and use it in GitHub Desktop.
test.zig
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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