munum 0.2.0

Micro 3D Math Library
Documentation
use super::ptr::Load;
use crate::{Mat2, Mat3, Mat4};
use alloc::boxed::Box;
use paste::paste;

macro_rules! export_mat {
    ($name:ident, $mat_type:ty, $t:ty) => {
        paste! {
            #[export_name = concat!(stringify!($name), "identity")]
            pub extern "C" fn [<$name _identity>]() -> *const $mat_type {
                Box::into_raw(Box::new(<$mat_type>::identity()))
            }

            #[export_name = concat!(stringify!($name), "add")]
            pub extern "C" fn [<$name _add>](
                out: *mut $mat_type,
                a: *const $mat_type,
                b: *const $mat_type,
            ) -> *const $mat_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 $mat_type,
                a: *const $mat_type,
                b: *const $mat_type,
            ) -> *const $mat_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 $mat_type,
                a: *const $mat_type,
                b: *const $mat_type,
            ) -> *const $mat_type {
                if let Some(o) = unsafe { out.as_mut() } {
                    *o = a.load();
                    *o *= b.load();
                }
                out
            }

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

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

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

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

macro_rules! export_mat_convert {
    ($from_name:ident, $from_type:ty, $to_name:ident, $to_type:ty) => {
        paste! {
            #[export_name = concat!(stringify!($to_name), "from", stringify!($from_name))]
            pub extern "C" fn [<$to_name _from_ $from_name>](m: *const $from_type) -> *const $to_type {
                Box::into_raw(Box::new(m.load().into()))
            }
        }
    }
}

export_mat!(mat2, Mat2<f64>, f64);
export_mat!(mat3, Mat3<f64>, f64);
export_mat!(mat4, Mat4<f64>, f64);

export_mat_convert!(mat2, Mat2<f64>, mat3, Mat3<f64>);
export_mat_convert!(mat3, Mat3<f64>, mat2, Mat2<f64>);
export_mat_convert!(mat3, Mat3<f64>, mat4, Mat4<f64>);
export_mat_convert!(mat4, Mat4<f64>, mat3, Mat3<f64>);

#[export_name = "normalmat3"]
pub extern "C" fn normal_mat3(out: *mut Mat3<f64>, m: *const Mat3<f64>) -> bool {
    if let Some(o) = unsafe { out.as_mut() } {
        *o = m.load();
        o.normal_matrix()
    } else {
        false
    }
}