organicomplex 0.7.0

Interactive complex-valued cellular automaton on 2D and 3D grids in search of that stuff - emergence, open-endedness, organicity etc.
use rand::prelude::*;

use serde::{
	Deserialize,
	Serialize
};

use std::{
	io::{
 		Read,
    	Write
	},
	ops::{
		Add,
		AddAssign,
		Div,
		DivAssign,
		Mul,
		MulAssign,
		Neg,
		Sub,
		SubAssign
	}
};

use super::rwbin::{
	ReadBin,
	WriteBin
};

// Fixed-point arithmetic with FPA_BINLOG bits for fractional part
#[derive(Clone, Copy, PartialEq, Debug, Deserialize, Serialize)]
pub struct Real (pub f64);

#[allow(dead_code)]
pub const REAL_UNIT: Real = Real(1.0);

#[allow(dead_code)]
pub const REAL_ZERO: Real = Real(0.0);

impl Real {
	#[allow(dead_code)]
	pub fn new(r: f64) -> Self {
		Self(r)
	}

	#[allow(dead_code)]
	pub fn new_default() -> Self {
		REAL_UNIT
	}

	#[allow(dead_code)]
	pub fn new_random(ampl: f64, irng: &mut impl Rng) -> Self {
		Self(irng.random_range(-ampl..=ampl))
	}

	#[allow(dead_code)]
	pub fn abs(&self) -> Self {
		Self(self.0.abs())
	}

	#[allow(dead_code)]
	pub fn min(&self, other: Self) -> Self {
		Self(self.0.min(other.0))
	}

	#[allow(dead_code)]
	pub fn max(&self, other: Self) -> Self {
		Self(self.0.max(other.0))
	}

}

impl From<f64> for Real {
	fn from(x: f64) -> Self {
		Self(x)
	}
}

// ----------------------------------------------------------------

impl Add for Real {
	type Output = Self;
    fn add(self, rhs: Self) -> Self {
        Self(self.0 + rhs.0)
    }
}

impl AddAssign for Real {
    fn add_assign(&mut self, rhs: Self) {
		self.0 += rhs.0;
    }
}

impl Div for Real {
	type Output = Self;
    fn div(self, rhs: Self) -> Self {
        Self(self.0 / rhs.0)
    }
}

impl DivAssign for Real {
    fn div_assign(&mut self, rhs: Self) {
		self.0 /= rhs.0;
    }
}

impl Mul for Real {
	type Output = Self;
	fn mul(self, rhs: Self) -> Self {
		Self(self.0 * rhs.0)
	}
}

impl MulAssign for Real {
	fn mul_assign(&mut self, rhs: Self) {
        self.0 *= rhs.0;
	}
}

impl Neg for Real {
	type Output = Self;
	fn neg(self) -> Self {
		Self(-self.0)
	}
}

impl Sub for Real {
	type Output = Self;
	fn sub(self, rhs: Self) -> Self {
        Self(self.0 - rhs.0)
    }
}

impl SubAssign for Real {
    fn sub_assign(&mut self, rhs: Self) {
		self.0 -= rhs.0;
    }
}

// ----------------------------------------------------------------

impl<W: Write> WriteBin<&Real> for W {
    fn write_bin(&mut self, x: &Real) -> Result<(), String> {
        self.write_bin(x.0)?;
        Ok(())
    }
}

impl<R: Read> ReadBin<Real> for R {
    fn read_bin(&mut self) -> Result<Real, String> {
        let r = self.read_bin()?;
        Ok(Real(r))
    }
}