use crate::{
nums::{
f32x4,
num_traits::{NumConstEx, PartialOrdEx},
},
DVec2, DVec3, DVec4, UnitDVec2, UnitDVec3, UnitDVec4, UnitVec2, UnitVec2x4, UnitVec3,
UnitVec3A, UnitVec3x4, UnitVec4, UnitVec4x4, Vec2, Vec2x4, Vec3, Vec3A, Vec3x4, Vec4, Vec4x4,
};
use auto_ops_det::{impl_op, impl_op_commutative};
macro_rules! impl_vec_dot_trait {
($scalar:ty, $general_vec:ty, $unit_vec:ty, $as_general_fn:ident) => {
impl_op!(dot |a: $general_vec, b: $general_vec| -> $scalar { <$general_vec>::dot(a, b) });
impl_op!(dot |a: $general_vec, b: &$general_vec| -> $scalar { <$general_vec>::dot(a, *b) });
impl_op!(dot |a: &$general_vec, b: $general_vec| -> $scalar { <$general_vec>::dot(*a, b) });
impl_op!(dot |a: &$general_vec, b: &$general_vec| -> $scalar { <$general_vec>::dot(*a, *b) });
impl_op_commutative!(dot |a: $general_vec, b: $unit_vec| -> $scalar { <$general_vec>::dot(a, b.$as_general_fn()) });
impl_op_commutative!(dot |a: $general_vec, b: &$unit_vec| -> $scalar { <$general_vec>::dot(a, b.$as_general_fn()) });
impl_op_commutative!(dot |a: &$general_vec, b: $unit_vec| -> $scalar { <$general_vec>::dot(*a, b.$as_general_fn()) });
impl_op_commutative!(dot |a: &$general_vec, b: &$unit_vec| -> $scalar { <$general_vec>::dot(*a, b.$as_general_fn()) });
};
}
macro_rules! impl_unit_vec_dot_clamp_trait {
($scalar:ty, $unit_vec:ty, $one:expr) => {
impl_op!(dot_clamp |a: $unit_vec, b: $unit_vec| -> $scalar { <$unit_vec>::dot(a, b).clamp(-$one, $one) });
impl_op!(dot_clamp |a: $unit_vec, b: &$unit_vec| -> $scalar { <$unit_vec>::dot(a, *b).clamp(-$one, $one) });
impl_op!(dot_clamp |a: &$unit_vec, b: $unit_vec| -> $scalar { <$unit_vec>::dot(*a, b).clamp(-$one, $one) });
impl_op!(dot_clamp |a: &$unit_vec, b: &$unit_vec| -> $scalar { <$unit_vec>::dot(*a, *b).clamp(-$one, $one) });
};
}
macro_rules! impl_vec_cross_trait {
($scalar:ty, $general_vec:ty, $unit_vec:ty, $as_general_fn:ident) => {
impl_op!(cross |a: $general_vec, b: $general_vec| -> $general_vec { <$general_vec>::cross(a, b) });
impl_op!(cross |a: $general_vec, b: &$general_vec| -> $general_vec { <$general_vec>::cross(a, *b) });
impl_op!(cross |a: &$general_vec, b: $general_vec| -> $general_vec { <$general_vec>::cross(*a, b) });
impl_op!(cross |a: &$general_vec, b: &$general_vec| -> $general_vec { <$general_vec>::cross(*a, *b) });
impl_op!(cross |a: $unit_vec, b: $unit_vec| -> $general_vec { <$unit_vec>::cross(a, b) });
impl_op!(cross |a: $unit_vec, b: &$unit_vec| -> $general_vec { <$unit_vec>::cross(a, *b) });
impl_op!(cross |a: &$unit_vec, b: $unit_vec| -> $general_vec { <$unit_vec>::cross(*a, b) });
impl_op!(cross |a: &$unit_vec, b: &$unit_vec| -> $general_vec { <$unit_vec>::cross(*a, *b) });
impl_op!(cross |a: $general_vec, b: $unit_vec| -> $general_vec { <$general_vec>::cross(a, b.$as_general_fn()) });
impl_op!(cross |a: $unit_vec, b: $general_vec| -> $general_vec { <$general_vec>::cross(a.$as_general_fn(), b) });
impl_op!(cross |a: $general_vec, b: &$unit_vec| -> $general_vec { <$general_vec>::cross(a, b.$as_general_fn()) });
impl_op!(cross |a: $unit_vec, b: &$general_vec| -> $general_vec { <$general_vec>::cross(a.$as_general_fn(), *b) });
impl_op!(cross |a: &$general_vec, b: $unit_vec| -> $general_vec { <$general_vec>::cross(*a, b.$as_general_fn()) });
impl_op!(cross |a: &$unit_vec, b: $general_vec| -> $general_vec { <$general_vec>::cross(a.$as_general_fn(), b) });
impl_op!(cross |a: &$general_vec, b: &$unit_vec| -> $general_vec { <$general_vec>::cross(*a, b.$as_general_fn()) });
impl_op!(cross |a: &$unit_vec, b: &$general_vec| -> $general_vec { <$general_vec>::cross(a.$as_general_fn(), *b) });
};
}
pub trait Dot<Rhs = Self> {
type Output;
fn dot(self, other: Rhs) -> Self::Output;
}
pub trait DotClamp<Rhs = Self> {
type Output;
fn dot_clamp(self, other: Rhs) -> Self::Output;
}
pub trait Cross<Rhs = Self> {
type Output;
fn cross(self, other: Rhs) -> Self::Output;
}
impl_vec_dot_trait!(f32, Vec2, UnitVec2, as_vec2);
impl_vec_dot_trait!(f32, Vec3, UnitVec3, as_vec3);
impl_vec_dot_trait!(f32, Vec4, UnitVec4, as_vec4);
impl_vec_dot_trait!(f32, Vec3A, UnitVec3A, as_vec3a);
impl_vec_dot_trait!(f64, DVec2, UnitDVec2, as_dvec2);
impl_vec_dot_trait!(f64, DVec3, UnitDVec3, as_dvec3);
impl_vec_dot_trait!(f64, DVec4, UnitDVec4, as_dvec4);
impl_vec_dot_trait!(f32x4, Vec2x4, UnitVec2x4, as_vec2x4);
impl_vec_dot_trait!(f32x4, Vec3x4, UnitVec3x4, as_vec3x4);
impl_vec_dot_trait!(f32x4, Vec4x4, UnitVec4x4, as_vec4x4);
impl_unit_vec_dot_clamp_trait!(f32, UnitVec2, 1.0);
impl_unit_vec_dot_clamp_trait!(f32, UnitVec3, 1.0);
impl_unit_vec_dot_clamp_trait!(f32, UnitVec3A, 1.0);
impl_unit_vec_dot_clamp_trait!(f32, UnitVec4, 1.0);
impl_unit_vec_dot_clamp_trait!(f64, UnitDVec2, 1.0);
impl_unit_vec_dot_clamp_trait!(f64, UnitDVec3, 1.0);
impl_unit_vec_dot_clamp_trait!(f64, UnitDVec4, 1.0);
impl_unit_vec_dot_clamp_trait!(f32x4, UnitVec2x4, f32x4::ONE);
impl_unit_vec_dot_clamp_trait!(f32x4, UnitVec3x4, f32x4::ONE);
impl_unit_vec_dot_clamp_trait!(f32x4, UnitVec4x4, f32x4::ONE);
impl_vec_cross_trait!(f32, Vec3, UnitVec3, as_vec3);
impl_vec_cross_trait!(f32, Vec3A, UnitVec3A, as_vec3a);
impl_vec_cross_trait!(f64, DVec3, UnitDVec3, as_dvec3);
impl_vec_cross_trait!(f32x4, Vec3x4, UnitVec3x4, as_vec3x4);