Files
fractal-poincare/main.rs
2025-09-15 16:30:08 +05:00

221 lines
5.3 KiB
Rust

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<f64> for Complex {
type Output = Self;
fn add(self, rhs: f64) -> Self::Output {
Complex::new(self.re + rhs, self.im)
}
}
impl Sub<f64> for Complex {
type Output = Self;
fn sub(self, rhs: f64) -> Self::Output {
Complex::new(self.re - rhs, self.im)
}
}
impl Mul<f64> for Complex {
type Output = Self;
fn mul(self, rhs: f64) -> Self::Output {
Complex::new(self.re * rhs, self.im * rhs)
}
}
impl Div<f64> 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<Complex> for f64 {
type Output = Complex;
fn add(self, rhs: Complex) -> Complex {
Complex::new(self + rhs.re, rhs.im)
}
}
impl Sub<Complex> for f64 {
type Output = Complex;
fn sub(self, rhs: Complex) -> Complex {
Complex::new(self - rhs.re, rhs.im)
}
}
impl Mul<Complex> for f64 {
type Output = Complex;
fn mul(self, rhs: Complex) -> Complex {
Complex::new(self * rhs.re, self * rhs.im)
}
}
impl Div<Complex> 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<String> = 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
}