glam_det 2.0.0

A simple and fast 3D math library for games and graphics.
Documentation
// Copyright (C) 2020-2025 glam-det authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

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;
    /// Clamp after dot of unit vectors to ensure the result is between -1 and 1
    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);