use laddu_core::{f64, Vec3, Vec4};
use numpy::PyArray1;
use pyo3::{exceptions::PyTypeError, prelude::*};
#[pyclass(name = "Vec3", module = "laddu", from_py_object)]
#[derive(Clone)]
pub struct PyVec3(pub Vec3);
#[pymethods]
impl PyVec3 {
#[new]
fn new(px: f64, py: f64, pz: f64) -> Self {
Self(Vec3::new(px, py, pz))
}
fn __add__(&self, other: &Bound<'_, PyAny>) -> PyResult<Self> {
if let Ok(other_vec) = other.extract::<PyRef<Self>>() {
Ok(Self(self.0 + other_vec.0))
} else if let Ok(other_int) = other.extract::<usize>() {
if other_int == 0 {
Ok(self.clone())
} else {
Err(PyTypeError::new_err(
"Addition with an integer for this type is only defined for 0",
))
}
} else {
Err(PyTypeError::new_err("Unsupported operand type for +"))
}
}
fn __radd__(&self, other: &Bound<'_, PyAny>) -> PyResult<Self> {
if let Ok(other_vec) = other.extract::<PyRef<Self>>() {
Ok(Self(other_vec.0 + self.0))
} else if let Ok(other_int) = other.extract::<usize>() {
if other_int == 0 {
Ok(self.clone())
} else {
Err(PyTypeError::new_err(
"Addition with an integer for this type is only defined for 0",
))
}
} else {
Err(PyTypeError::new_err("Unsupported operand type for +"))
}
}
fn __sub__(&self, other: &Bound<'_, PyAny>) -> PyResult<Self> {
if let Ok(other_vec) = other.extract::<PyRef<Self>>() {
Ok(Self(self.0 - other_vec.0))
} else if let Ok(other_int) = other.extract::<usize>() {
if other_int == 0 {
Ok(self.clone())
} else {
Err(PyTypeError::new_err(
"Subtraction with an integer for this type is only defined for 0",
))
}
} else {
Err(PyTypeError::new_err("Unsupported operand type for -"))
}
}
fn __rsub__(&self, other: &Bound<'_, PyAny>) -> PyResult<Self> {
if let Ok(other_vec) = other.extract::<PyRef<Self>>() {
Ok(Self(other_vec.0 - self.0))
} else if let Ok(other_int) = other.extract::<usize>() {
if other_int == 0 {
Ok(self.clone())
} else {
Err(PyTypeError::new_err(
"Subtraction with an integer for this type is only defined for 0",
))
}
} else {
Err(PyTypeError::new_err("Unsupported operand type for -"))
}
}
fn __mul__(&self, other: f64) -> Self {
Self(self.0 * other)
}
fn __rmul__(&self, other: f64) -> Self {
Self(self.0 * other)
}
fn __neg__(&self) -> PyResult<Self> {
Ok(Self(-self.0))
}
pub fn dot(&self, other: Self) -> f64 {
self.0.dot(&other.0)
}
fn cross(&self, other: Self) -> Self {
Self(self.0.cross(&other.0))
}
#[getter]
fn mag(&self) -> f64 {
self.0.mag()
}
#[getter]
fn mag2(&self) -> f64 {
self.0.mag2()
}
#[getter]
fn costheta(&self) -> f64 {
self.0.costheta()
}
#[getter]
fn theta(&self) -> f64 {
self.0.theta()
}
#[getter]
fn phi(&self) -> f64 {
self.0.phi()
}
#[getter]
fn unit(&self) -> Self {
Self(self.0.unit())
}
#[getter]
fn px(&self) -> f64 {
self.0.px()
}
#[getter]
fn x(&self) -> f64 {
self.0.x
}
#[getter]
fn py(&self) -> f64 {
self.0.py()
}
#[getter]
fn y(&self) -> f64 {
self.0.y
}
#[getter]
fn pz(&self) -> f64 {
self.0.pz()
}
#[getter]
fn z(&self) -> f64 {
self.0.z
}
fn with_mass(&self, mass: f64) -> PyVec4 {
PyVec4(self.0.with_mass(mass))
}
fn with_energy(&self, mass: f64) -> PyVec4 {
PyVec4(self.0.with_energy(mass))
}
fn to_numpy<'py>(&self, py: Python<'py>) -> Bound<'py, PyArray1<f64>> {
PyArray1::from_vec(py, self.0.into())
}
#[staticmethod]
fn from_array(array: Vec<f64>) -> Self {
Self::new(array[0], array[1], array[2])
}
fn __repr__(&self) -> String {
format!("{:?}", self.0)
}
fn __str__(&self) -> String {
format!("{}", self.0)
}
}
#[pyclass(name = "Vec4", module = "laddu", from_py_object)]
#[derive(Clone)]
pub struct PyVec4(pub Vec4);
#[pymethods]
impl PyVec4 {
#[new]
fn new(px: f64, py: f64, pz: f64, e: f64) -> Self {
Self(Vec4::new(px, py, pz, e))
}
fn __add__(&self, other: &Bound<'_, PyAny>) -> PyResult<Self> {
if let Ok(other_vec) = other.extract::<PyRef<Self>>() {
Ok(Self(self.0 + other_vec.0))
} else if let Ok(other_int) = other.extract::<usize>() {
if other_int == 0 {
Ok(self.clone())
} else {
Err(PyTypeError::new_err(
"Addition with an integer for this type is only defined for 0",
))
}
} else {
Err(PyTypeError::new_err("Unsupported operand type for +"))
}
}
fn __radd__(&self, other: &Bound<'_, PyAny>) -> PyResult<Self> {
if let Ok(other_vec) = other.extract::<PyRef<Self>>() {
Ok(Self(other_vec.0 + self.0))
} else if let Ok(other_int) = other.extract::<usize>() {
if other_int == 0 {
Ok(self.clone())
} else {
Err(PyTypeError::new_err(
"Addition with an integer for this type is only defined for 0",
))
}
} else {
Err(PyTypeError::new_err("Unsupported operand type for +"))
}
}
fn __sub__(&self, other: &Bound<'_, PyAny>) -> PyResult<Self> {
if let Ok(other_vec) = other.extract::<PyRef<Self>>() {
Ok(Self(self.0 - other_vec.0))
} else if let Ok(other_int) = other.extract::<usize>() {
if other_int == 0 {
Ok(self.clone())
} else {
Err(PyTypeError::new_err(
"Subtraction with an integer for this type is only defined for 0",
))
}
} else {
Err(PyTypeError::new_err("Unsupported operand type for -"))
}
}
fn __rsub__(&self, other: &Bound<'_, PyAny>) -> PyResult<Self> {
if let Ok(other_vec) = other.extract::<PyRef<Self>>() {
Ok(Self(other_vec.0 - self.0))
} else if let Ok(other_int) = other.extract::<usize>() {
if other_int == 0 {
Ok(self.clone())
} else {
Err(PyTypeError::new_err(
"Subtraction with an integer for this type is only defined for 0",
))
}
} else {
Err(PyTypeError::new_err("Unsupported operand type for -"))
}
}
fn __mul__(&self, other: f64) -> Self {
Self(self.0 * other)
}
fn __rmul__(&self, other: f64) -> Self {
Self(self.0 * other)
}
fn __neg__(&self) -> PyResult<Self> {
Ok(Self(-self.0))
}
#[getter]
fn mag(&self) -> f64 {
self.0.mag()
}
#[getter]
fn mag2(&self) -> f64 {
self.0.mag2()
}
#[getter]
fn vec3(&self) -> PyVec3 {
PyVec3(self.0.vec3())
}
fn boost(&self, beta: &PyVec3) -> Self {
Self(self.0.boost(&beta.0))
}
#[getter]
fn e(&self) -> f64 {
self.0.e()
}
#[getter]
fn t(&self) -> f64 {
self.0.t
}
#[getter]
fn px(&self) -> f64 {
self.0.px()
}
#[getter]
fn x(&self) -> f64 {
self.0.x
}
#[getter]
fn py(&self) -> f64 {
self.0.py()
}
#[getter]
fn y(&self) -> f64 {
self.0.y
}
#[getter]
fn pz(&self) -> f64 {
self.0.pz()
}
#[getter]
fn z(&self) -> f64 {
self.0.z
}
#[getter]
fn momentum(&self) -> PyVec3 {
PyVec3(self.0.momentum())
}
#[getter]
fn gamma(&self) -> f64 {
self.0.gamma()
}
#[getter]
fn beta(&self) -> PyVec3 {
PyVec3(self.0.beta())
}
#[getter]
fn m(&self) -> f64 {
self.0.m()
}
#[getter]
fn m2(&self) -> f64 {
self.0.m2()
}
fn to_numpy<'py>(&self, py: Python<'py>) -> Bound<'py, PyArray1<f64>> {
PyArray1::from_vec(py, self.0.into())
}
#[staticmethod]
fn from_array(array: Vec<f64>) -> Self {
Self::new(array[0], array[1], array[2], array[3])
}
fn __str__(&self) -> String {
format!("{}", self.0)
}
fn __repr__(&self) -> String {
self.0.to_p4_string()
}
}