munum 0.2.0

Micro 3D Math Library
Documentation
use super::ptr::Load;
use crate::{Mat2, Mat3, Mat4, Vec2, Vec3, Vec4};
use paste::paste;

macro_rules! export_vec {
    ($name:ident, $vec_type:ty, $mat_type:ty, $t:ty) => {
        paste! {
            #[export_name = concat!(stringify!($name), "add")]
            pub extern "C" fn [<$name _add>](
                out: *mut $vec_type,
                a: *const $vec_type,
                b: *const $vec_type,
            ) -> *const $vec_type {
                if let Some(o) = unsafe { out.as_mut() } {
                    *o = a.load();
                    *o += b.load();
                }
                out
            }

            #[export_name = concat!(stringify!($name), "sub")]
            pub extern "C" fn [<$name _sub>](
                out: *mut $vec_type,
                a: *const $vec_type,
                b: *const $vec_type,
            ) -> *const $vec_type {
                if let Some(o) = unsafe { out.as_mut() } {
                    *o = a.load();
                    *o -= b.load();
                }
                out
            }

            #[export_name = concat!(stringify!($name), "mul")]
            pub extern "C" fn [<$name _mul>](
                out: *mut $vec_type,
                m: *const $mat_type,
                a: *const $vec_type,
            ) -> *const $vec_type {
                if let Some(o) = unsafe { out.as_mut() } {
                    *o = m.load() * a.load();
                }
                out
            }

            #[export_name = concat!(stringify!($name), "scale")]
            pub extern "C" fn [<$name _scale>](out: *mut $vec_type, a: *const $vec_type, s: f64) -> *const $vec_type {
                if let Some(o) = unsafe { out.as_mut() } {
                    *o = a.load();
                    *o *= s;
                }
                out
            }

            #[export_name = concat!(stringify!($name), "norm")]
            pub extern "C" fn [<$name _norm>](out: *mut $vec_type, a: *const $vec_type) -> bool {
                if let Some(o) = unsafe { out.as_mut() } {
                    *o = a.load();
                    o.normalize()
                } else {
                    false
                }
            }

            #[export_name = concat!(stringify!($name), "dot")]
            pub extern "C" fn [<$name _dot>](a: *const $vec_type, b: *const $vec_type) -> $t {
                a.load().dot(b.load())
            }

            #[export_name = concat!(stringify!($name), "lerp")]
            pub extern "C" fn [<$name _lerp>](
                out: *mut $vec_type,
                a: *const $vec_type,
                b: *const $vec_type,
                t: $t,
            ) -> *const $vec_type {
                if let Some(o) = unsafe { out.as_mut() } {
                    *o = a.load().lerp(b.load(), t);
                }
                out
            }
        }
    }
}

export_vec!(vec2, Vec2<f64>, Mat2<f64>, f64);
export_vec!(vec3, Vec3<f64>, Mat3<f64>, f64);
export_vec!(vec4, Vec4<f64>, Mat4<f64>, f64);

#[export_name = "mat3vec2mul"]
pub extern "C" fn mat3_mul_vec2(
    out: *mut Vec2<f64>,
    m: *const Mat3<f64>,
    a: *const Vec2<f64>,
) -> *const Vec2<f64> {
    if let Some(o) = unsafe { out.as_mut() } {
        *o = (m.load() * Vec3::from(a.load())).into();
    }
    out
}

#[export_name = "mat4vec3mul"]
pub extern "C" fn mat4_mul_vec3(
    out: *mut Vec3<f64>,
    m: *const Mat4<f64>,
    a: *const Vec3<f64>,
) -> *const Vec3<f64> {
    if let Some(o) = unsafe { out.as_mut() } {
        *o = (m.load() * Vec4::from(a.load())).into();
    }
    out
}

#[export_name = "vec3cross"]
pub extern "C" fn vec3_cross(
    out: *mut Vec3<f64>,
    a: *const Vec3<f64>,
    b: *const Vec3<f64>,
) -> *const Vec3<f64> {
    if let Some(o) = unsafe { out.as_mut() } {
        *o = a.load().cross(b.load());
    }
    out
}