#![cfg_attr(not(feature = "std"), no_std)]
extern crate alloc;
mod dir3;
mod dual;
mod mat3;
mod mat4;
mod point2;
mod point3;
mod quat;
mod scalar;
mod spatial;
mod transform;
mod vec2;
mod vec3;
mod vec4;
#[cfg(feature = "exact")]
pub mod predicates;
pub use dir3::Dir3;
pub use dual::Dual;
pub use mat3::Mat3;
pub use mat4::Mat4;
pub use point2::Point2;
pub use point3::Point3;
pub use quat::Quat;
pub use scalar::Scalar;
pub use spatial::{SpatialInertia, SpatialMat, SpatialTransform, SpatialVec};
pub use transform::Transform;
pub use vec2::Vec2;
pub use vec3::Vec3;
pub use vec4::Vec4;
pub fn skew<S: Scalar>(v: &Vec3<S>) -> Mat3<S> {
Mat3::new(S::ZERO, -v.z, v.y, v.z, S::ZERO, -v.x, -v.y, v.x, S::ZERO)
}
pub const GRAVITY: f64 = 9.81;
#[cfg(feature = "bytemuck")]
mod bytemuck_impls {
use super::*;
macro_rules! impl_pod {
($t:ty) => {
unsafe impl bytemuck::Zeroable for $t {}
unsafe impl bytemuck::Pod for $t {}
};
}
impl_pod!(Vec2<f32>);
impl_pod!(Vec2<f64>);
impl_pod!(Vec3<f32>);
impl_pod!(Vec3<f64>);
impl_pod!(Vec4<f32>);
impl_pod!(Vec4<f64>);
impl_pod!(Point2<f32>);
impl_pod!(Point2<f64>);
impl_pod!(Point3<f32>);
impl_pod!(Point3<f64>);
impl_pod!(Mat3<f32>);
impl_pod!(Mat3<f64>);
impl_pod!(Mat4<f32>);
impl_pod!(Mat4<f64>);
impl_pod!(Quat<f32>);
impl_pod!(Quat<f64>);
impl_pod!(Transform<f32>);
impl_pod!(Transform<f64>);
impl_pod!(SpatialVec<f32>);
impl_pod!(SpatialVec<f64>);
impl_pod!(SpatialMat<f32>);
impl_pod!(SpatialMat<f64>);
impl_pod!(SpatialTransform<f32>);
impl_pod!(SpatialTransform<f64>);
impl_pod!(SpatialInertia<f32>);
impl_pod!(SpatialInertia<f64>);
unsafe impl bytemuck::TransparentWrapper<Vec3<f32>> for Dir3<f32> {}
unsafe impl bytemuck::TransparentWrapper<Vec3<f64>> for Dir3<f64> {}
}
#[cfg(feature = "la")]
pub mod la;
#[cfg(feature = "ad")]
pub mod ad;
#[cfg(feature = "expr")]
pub mod expr;
#[cfg(feature = "gpu")]
pub mod gpu;
#[cfg(feature = "compute")]
pub mod compute;
#[cfg(feature = "tensor")]
pub mod tensor;
#[cfg(feature = "optim")]
pub mod optim;
#[cfg(feature = "train")]
pub mod train;
#[cfg(feature = "safetensors")]
pub mod safetensors;
#[cfg(feature = "splatting")]
pub mod splatting;
#[cfg(feature = "holo")]
pub mod holo;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn skew_cross_product() {
let v = Vec3::new(1.0, 2.0, 3.0);
let w = Vec3::new(4.0, 5.0, 6.0);
let skew_v = skew(&v);
let result = skew_v * w;
let expected = v.cross(w);
assert!((result.x - expected.x).abs() < 1e-10);
assert!((result.y - expected.y).abs() < 1e-10);
assert!((result.z - expected.z).abs() < 1e-10);
}
#[test]
fn skew_antisymmetric() {
let v = Vec3::new(1.0, 2.0, 3.0);
let s = skew(&v);
let st = s.transpose();
let sum = s + st;
assert!((sum.c0.norm_sq() + sum.c1.norm_sq() + sum.c2.norm_sq()) < 1e-20);
}
#[test]
fn mat4_add_sub_neg_scale() {
let a = Mat4::<f64>::identity();
let b = Mat4::<f64>::identity();
let sum = a + b;
assert!((sum.get(0, 0) - 2.0).abs() < 1e-10);
let diff = a - b;
assert!(diff.get(0, 0).abs() < 1e-10);
let neg = -a;
assert!((neg.get(0, 0) - (-1.0)).abs() < 1e-10);
let scaled = a * 3.0;
assert!((scaled.get(0, 0) - 3.0).abs() < 1e-10);
}
#[test]
fn spatial_mat_neg_scale_mul_vec() {
let m = SpatialMat::<f64>::identity();
let v = SpatialVec::new(Vec3::new(1.0, 2.0, 3.0), Vec3::new(4.0, 5.0, 6.0));
let result = m * v;
assert_eq!(result.angular, v.angular);
assert_eq!(result.linear, v.linear);
let neg = -m;
let result2 = neg * v;
assert_eq!(result2.angular, -v.angular);
assert_eq!(result2.linear, -v.linear);
let scaled = m * 2.0;
let result3 = scaled * v;
assert!((result3.angular.x - 2.0).abs() < 1e-10);
}
}