rust-roche 0.1.4

Rust translation of Tom Marsh's cpp-roche package for modelling Roche distorted stars/binary systems.
Documentation
use std::ops;
use pyo3::prelude::*;

// useful for defining python operators
#[derive(FromPyObject)]
enum Vec3OrF64 {
    Vec3(Vec3),
    F64(f64)
}

#[pyclass(from_py_object)]
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct Vec3 {
    #[pyo3(get, set)]
    pub x: f64,
    #[pyo3(get, set)]
    pub y: f64,
    #[pyo3(get, set)]
    pub z: f64,
}

#[pymethods]
impl Vec3 {
    #[new]
    pub fn new(x: f64, y: f64, z: f64) -> Self {
        Self {
            x: x,
            y: y,
            z: z
        }
    }
    
    #[staticmethod]
    pub fn cofm1() -> Self {
        Self {
            x: 0.0,
            y: 0.0,
            z: 0.0
        }
    }

    #[staticmethod]
    pub fn cofm2() -> Self {
        Self {
            x: 1.0,
            y: 0.0,
            z: 0.0
        }
    }

    pub fn set(&mut self, x: f64, y: f64, z: f64) -> () {
        self.x = x;
        self.y = y;
        self.z = z;
    }

    // Normalises the vector in place
    pub fn unit(&mut self) {
        let norm = self.length();
        self.x /= norm;
        self.y /= norm;
        self.z /= norm;
    }

    // Returns a normalised version of the vector
    pub fn norm(&self) -> Self {
        let norm = self.length();
        Self {
            x: self.x / norm,
            y: self.y / norm,
            z: self.z / norm
        }
    }

    // For `__repr__` we want to return a string that Python code could use to recreate
    // the `Vec3`, like `Vec3(5, 6, 7)` for example.
    fn __repr__(&self) -> String {
        // We use the `format!` macro to create a string. Its first argument is a
        // format string, followed by any number of parameters which replace the
        // `{}`'s in the format string.
        format!("Vec3({}, {}, {})", self.x, self.y, self.z)
    }

    // Returns the length of the vector
    pub fn length(&self) -> f64 {
        (self.x.powi(2) + self.y.powi(2) + self.z.powi(2)).sqrt()
    }

    // Returns the squared length of the vector
    pub fn sqr(&self) -> f64 {
        self.x.powi(2) + self.y.powi(2) + self.z.powi(2)
    }

    // Returns the dot product of two vectors
    pub fn dot(&self, other: &Vec3) -> f64 {
        self.x*other.x + self.y*other.y + self.z*other.z
    }

    // Returns the cross product of two vectors
    pub fn cross(&self, other: &Vec3) -> Vec3 {
        let temp_x = self.y*other.z - self.z*other.y;
        let temp_y = self.z*other.x - self.x*other.z;
        let temp_z = self.x*other.y - self.y*other.x;
        Vec3::new(temp_x, temp_y, temp_z)
    }

    // Python dunder methods for arithmetic
    fn __add__(&self, other: Vec3OrF64) -> Self {
        match other {
            Vec3OrF64::Vec3(v) => self.clone() + v,
            Vec3OrF64::F64(f) => self.clone() + f
        }
    }
    fn __radd__(&self, other: Vec3OrF64) -> Self {
        match other {
            Vec3OrF64::Vec3(v) => v + self.clone(),
            Vec3OrF64::F64(f) => f + self.clone()
        }
    }
    fn __sub__(&self, other: Vec3OrF64) -> Self {
        match other {
            Vec3OrF64::Vec3(v) => self.clone() - v,
            Vec3OrF64::F64(f) => self.clone() - f
        }
    }
    fn __rsub__(&self, other: Vec3OrF64) -> Self {
        match other {
            Vec3OrF64::Vec3(v) => v - self.clone(),
            Vec3OrF64::F64(f) => f - self.clone()   
        }
    }
    fn __mul__(&self, other: f64) -> Self {
        self.clone() * other
    }
    fn __rmul__(&self, other: f64) -> Self {
        other * self.clone()
    }
    fn __truediv__(&self, other: f64) -> Self {
        self.clone() / other
    }
    fn __rtruediv__(&self, other: f64) -> Self {
        other / self.clone()
    }
    fn __neg__(&self) -> Self {
        -self.clone()
    }

}

// in-place multiplication by f64
impl ops::MulAssign<f64> for Vec3 {
    fn mul_assign(&mut self, rhs: f64) {
        self.x *= rhs;
        self.y *= rhs;
        self.z *= rhs;
    }
}

// in-place division by f64
impl ops::DivAssign<f64> for Vec3 {
    fn div_assign(&mut self, rhs: f64) {
        self.x /= rhs;
        self.y /= rhs;
        self.z /= rhs;
    }
}

// in-place addition of vector
impl ops::AddAssign<Vec3> for Vec3 {
    fn add_assign(&mut self, rhs: Vec3) {
        self.x += rhs.x;
        self.y += rhs.y;
        self.z += rhs.z;
    }
}


// in-place subtraction of vector
impl ops::SubAssign<Vec3> for Vec3 {
    fn sub_assign(&mut self, rhs: Vec3) {
        self.x -= rhs.x;
        self.y -= rhs.y;
        self.z -= rhs.z;
    }
}

// Sum of two vectors
impl ops::Add for Vec3 {
    type Output = Self;
    fn add(self, other: Self) -> Self {
        Self {
            x: self.x + other.x,
            y: self.y + other.y,
            z: self.z + other.z,
        }
    }
}

// Sum of vector and f64
impl ops::Add<f64> for Vec3 {
    type Output = Self;
    fn add(self, other: f64) -> Self {
        Self {
            x: self.x + other,
            y: self.y + other,
            z: self.z + other,
        }
    }
}

// Sum of f64 and vector
impl ops::Add<Vec3> for f64 {
    type Output = Vec3;
    fn add(self, other: Vec3) -> Vec3 {
        Vec3 {
            x: self + other.x,
            y: self + other.y,
            z: self + other.z,
        }
    }
}

// Difference between two vectors
impl ops::Sub for Vec3 {
    type Output = Self;
    fn sub(self, other: Self) -> Self {
        Self {
            x: self.x - other.x,
            y: self.y - other.y,
            z: self.z - other.z,
        }
    }
}

// Difference between vector and f64
impl ops::Sub<f64> for Vec3 {
    type Output = Self;
    fn sub(self, other: f64) -> Self {
        Self {
            x: self.x - other,
            y: self.y - other,
            z: self.z - other,
        }
    }
}

// Difference between f64 and vector
impl ops::Sub<Vec3> for f64 {
    type Output = Vec3;
    fn sub(self, other: Vec3) -> Vec3 {
        Vec3 {
            x: self - other.x,
            y: self - other.y,
            z: self - other.z,
        }
    }
}

// Multiplication of Vec3 by f64
impl ops::Mul<f64> for Vec3 {
    type Output = Self;

    fn mul(self, rhs: f64) -> Self {
        Self{
            x: self.x * rhs,
            y: self.y * rhs,
            z: self.z * rhs,
        }
    }
}

// Multiplication of f64 by Vec3
impl ops::Mul<Vec3> for f64 {
    type Output = Vec3;

    fn mul(self, rhs: Vec3) -> Vec3 {
        Vec3{
            x: self * rhs.x,
            y: self * rhs.y,
            z: self * rhs.z,
        }
    }
}

// Division of Vec3 by f64
impl ops::Div<f64> for Vec3 {
    type Output = Self;

    fn div(self, rhs: f64) -> Self {
        Self{
            x: self.x / rhs,
            y: self.y / rhs,
            z: self.z / rhs,
        }
    }
}

// Division of f64 by Vec3
impl ops::Div<Vec3> for f64 {
    type Output = Vec3;

    fn div(self, rhs: Vec3) -> Vec3 {
        Vec3{
            x: self / rhs.x,
            y: self / rhs.y,
            z: self / rhs.z,
        }
    }
}

// Negative of a vector
impl ops::Neg for Vec3 {
    type Output = Self;

    fn neg(self) -> Self {
        Vec3{
            x: -self.x,
            y: -self.y,
            z: -self.z,
        }
    }
}