use std::env; use std::fmt::Write; use std::ops::{Add, Div, Mul, Sub}; #[derive(Debug, Clone, Copy)] struct Complex { re: f64, im: f64, } impl Complex { fn new(re: f64, im: f64) -> Self { Complex { re, im } } fn abs(&self) -> f64 { (self.re * self.re + self.im * self.im).sqrt() } fn powi(&self, mut n: i32) -> Self { if n == 0 { return Complex::new(1.0, 0.0); } if n < 0 { return Complex::new(1.0, 0.0) / self.powi(-n); } let mut base = *self; let mut result = Complex::new(1.0, 0.0); while n > 0 { if n % 2 == 1 { result = result * base; } base = base * base; n /= 2; } result } } // === Complex to Complex === impl Add for Complex { type Output = Self; fn add(self, rhs: Self) -> Self::Output { Complex::new(self.re + rhs.re, self.im + rhs.im) } } impl Sub for Complex { type Output = Self; fn sub(self, rhs: Self) -> Self::Output { Complex::new(self.re - rhs.re, self.im - rhs.im) } } impl Mul for Complex { type Output = Self; fn mul(self, rhs: Self) -> Self::Output { Complex::new( self.re * rhs.re - self.im * rhs.im, self.re * rhs.im + self.im * rhs.re, ) } } impl Div for Complex { type Output = Self; fn div(self, rhs: Self) -> Self::Output { let denom = rhs.re * rhs.re + rhs.im * rhs.im; Complex::new( (self.re * rhs.re + self.im * rhs.im) / denom, (self.im * rhs.re - self.re * rhs.im) / denom, ) } } // === Complex to f64 === impl Add for Complex { type Output = Self; fn add(self, rhs: f64) -> Self::Output { Complex::new(self.re + rhs, self.im) } } impl Sub for Complex { type Output = Self; fn sub(self, rhs: f64) -> Self::Output { Complex::new(self.re - rhs, self.im) } } impl Mul for Complex { type Output = Self; fn mul(self, rhs: f64) -> Self::Output { Complex::new(self.re * rhs, self.im * rhs) } } impl Div for Complex { type Output = Self; fn div(self, rhs: f64) -> Self::Output { Complex::new(self.re / rhs, self.im / rhs) } } // === f64 to Complex === impl Add for f64 { type Output = Complex; fn add(self, rhs: Complex) -> Complex { Complex::new(self + rhs.re, rhs.im) } } impl Sub for f64 { type Output = Complex; fn sub(self, rhs: Complex) -> Complex { Complex::new(self - rhs.re, rhs.im) } } impl Mul for f64 { type Output = Complex; fn mul(self, rhs: Complex) -> Complex { Complex::new(self * rhs.re, self * rhs.im) } } impl Div for f64 { type Output = Complex; fn div(self, rhs: Complex) -> Complex { Complex::new(self, 0.0) / rhs } } #[derive(Debug)] struct Args { size: u32, depth: u8, g2: Complex, g3: Complex, } fn parse_args() -> Args { let mut args_struct = Args { size: 128, depth: 8, g2: Complex::new(0.0, 0.0), g3: Complex::new(1.0, 0.0), }; let args: Vec = env::args().skip(1).collect(); let mut i = 0; while i < args.len() { match args[i].as_str() { "--size" | "-s" => { if i + 1 < args.len() { args_struct.size = args[i + 1].parse().unwrap_or(args_struct.size); i += 1; } } "--depth" | "-d" => { if i + 1 < args.len() { args_struct.depth = args[i + 1].parse().unwrap_or(args_struct.depth); i += 1; } } "-g2" => { if i + 1 < args.len() { let val: f64 = args[i + 1].parse().unwrap_or(args_struct.g2.re); args_struct.g2 = Complex::new(val, 0.0); i += 1; } } "-g3" => { if i + 1 < args.len() { let val: f64 = args[i + 1].parse().unwrap_or(args_struct.g3.re); args_struct.g3 = Complex::new(val, 0.0); i += 1; } } _ => {} } i += 1; } args_struct } fn main() { let args = parse_args(); println!("{}", fractal(args.size, args.depth, args.g2, args.g3)); } fn fractal(size: u32, depth: u8, g2: Complex, g3: Complex) -> String { let xi: f64 = -2.0; let yi: f64 = -2.0; let xf: f64 = 2.0; let yf: f64 = 2.0; let mut code = String::with_capacity((size * size * 3) as usize); for y in 0..=size - 1 { let zy = y as f64 * (yf - yi) / (size as f64 - 1.0) + yi; for x in 0..=size - 1 { let zx = x as f64 * (xf - xi) / (size as f64 - 1.0) + xi; let mut z = Complex::new(zx, zy); for i in 0..=depth - 1 { if z.abs() > 2.0 { write!(&mut code, "{}", i).unwrap(); break; } z = (z.powi(4) + 0.5 * g2 * z.powi(2) + 2.0 * g3 * z + 1.0 / 16.0 * g2.powi(2)) / (4.0 * z.powi(3) - g2 * z - g3) } } } code }