use core::ops::{Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Neg, Sub, SubAssign};
use num_traits::{MulAdd, MulAddAssign, One, Signed, Zero, float::FloatCore};
use crate::{MathConstants, SqrtMethods, Vector2dMath};
pub type Vector2df32 = Vector2d<f32>;
pub type Vector2df64 = Vector2d<f64>;
#[repr(C, align(8))]
#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct Vector2d<T> {
pub x: T,
pub y: T,
}
impl<T> Vector2d<T>
where
T: Copy,
{
#[inline(always)]
pub const fn new(x: T, y: T) -> Self {
Self { x, y }
}
}
impl<T> Zero for Vector2d<T>
where
T: Copy + Zero + PartialEq + Vector2dMath,
{
#[inline(always)]
fn zero() -> Self {
Self { x: T::zero(), y: T::zero() }
}
#[inline(always)]
fn is_zero(&self) -> bool {
self.x == T::zero() && self.y == T::zero()
}
}
impl<T> Neg for Vector2d<T>
where
T: Copy + Vector2dMath,
{
type Output = Self;
#[inline(always)]
fn neg(self) -> Self {
T::v2_neg(self)
}
}
impl<T> Add for Vector2d<T>
where
T: Copy + Vector2dMath,
{
type Output = Self;
#[inline(always)]
fn add(self, other: Self) -> Self {
T::v2_add(self, other)
}
}
impl<T> AddAssign for Vector2d<T>
where
T: Copy + Vector2dMath,
{
#[inline(always)]
fn add_assign(&mut self, other: Self) {
*self = *self + other;
}
}
impl<T> MulAdd<T> for Vector2d<T>
where
T: Copy + Vector2dMath,
{
type Output = Self;
#[inline(always)]
fn mul_add(self, k: T, other: Self) -> Self {
T::v2_mul_add(self, k, other)
}
}
impl<T> MulAddAssign<T> for Vector2d<T>
where
T: Copy + Vector2dMath,
{
#[inline(always)]
fn mul_add_assign(&mut self, k: T, other: Self) {
*self = self.mul_add(k, other);
}
}
impl<T> Sub for Vector2d<T>
where
T: Copy + Vector2dMath,
{
type Output = Self;
#[inline(always)]
fn sub(self, other: Self) -> Self {
self + (-other)
}
}
impl<T> SubAssign for Vector2d<T>
where
T: Copy + Vector2dMath,
{
#[inline(always)]
fn sub_assign(&mut self, other: Self) {
*self = *self - other;
}
}
impl Mul<Vector2d<f32>> for f32 {
type Output = Vector2d<f32>;
#[inline(always)]
fn mul(self, other: Vector2d<f32>) -> Vector2d<f32> {
f32::v2_mul_scalar(other, self)
}
}
impl Mul<Vector2d<f64>> for f64 {
type Output = Vector2d<f64>;
#[inline(always)]
fn mul(self, other: Vector2d<f64>) -> Vector2d<f64> {
f64::v2_mul_scalar(other, self)
}
}
impl<T> Mul<T> for Vector2d<T>
where
T: Copy + Vector2dMath,
{
type Output = Self;
#[inline(always)]
fn mul(self, k: T) -> Self {
T::v2_mul_scalar(self, k)
}
}
impl<T> MulAssign<T> for Vector2d<T>
where
T: Copy + Vector2dMath,
{
#[inline(always)]
fn mul_assign(&mut self, k: T) {
*self = *self * k;
}
}
impl<T> Div<T> for Vector2d<T>
where
T: Copy + Vector2dMath,
{
type Output = Self;
#[inline(always)]
fn div(self, k: T) -> Self {
T::v2_div_scalar(self, k)
}
}
impl<T> DivAssign<T> for Vector2d<T>
where
T: Copy + Vector2dMath,
{
#[inline(always)]
fn div_assign(&mut self, k: T) {
*self = self.div(k);
}
}
impl<T> Index<usize> for Vector2d<T> {
type Output = T;
#[inline(always)]
fn index(&self, index: usize) -> &T {
match index {
0 => &self.x,
_ => &self.y, }
}
}
impl<T> IndexMut<usize> for Vector2d<T> {
#[inline(always)]
fn index_mut(&mut self, index: usize) -> &mut T {
match index {
0 => &mut self.x,
_ => &mut self.y, }
}
}
impl<T> Vector2d<T>
where
T: Copy + Signed,
{
#[inline(always)]
pub fn abs(self) -> Self {
Self { x: self.x.abs(), y: self.y.abs() }
}
#[inline(always)]
pub fn abs_in_place(&mut self) -> &mut Self {
*self = self.abs();
self
}
}
impl<T> Vector2d<T>
where
T: Copy + FloatCore,
{
#[inline(always)]
pub fn clamp(self, min: T, max: T) -> Self {
Self { x: self.x.clamp(min, max), y: self.y.clamp(min, max) }
}
#[inline(always)]
pub fn clamp_in_place(&mut self, min: T, max: T) -> &mut Self {
*self = self.clamp(min, max);
self
}
}
impl<T> Vector2d<T>
where
T: Copy + Vector2dMath,
{
#[inline(always)]
pub fn dot(self, other: Self) -> T {
T::v2_dot(self, other)
}
}
impl<T> Vector2d<T>
where
T: Copy + Vector2dMath,
{
#[inline(always)]
pub fn cross(self, other: Self) -> T {
T::v2_cross(self, other)
}
}
impl<T> Vector2d<T>
where
T: Copy + Vector2dMath,
{
#[inline(always)]
pub fn norm_squared(self) -> T {
T::v2_norm_squared(self)
}
#[inline(always)]
pub fn distance_squared(self, other: Self) -> T {
(self - other).norm_squared()
}
}
impl<T> Vector2d<T>
where
T: Copy + SqrtMethods + Vector2dMath,
{
#[inline(always)]
pub fn norm(self) -> T {
Self::norm_squared(self).sqrt()
}
}
impl<T> Vector2d<T>
where
T: Copy + Zero + PartialEq + SqrtMethods + Vector2dMath,
{
#[inline(always)]
pub fn normalize(self) -> Self {
let norm_squared = self.norm_squared();
if norm_squared == T::zero() {
return self;
}
self * norm_squared.sqrt_reciprocal()
}
#[inline(always)]
pub fn normalize_in_place(&mut self) -> &mut Self {
*self = self.normalize();
self
}
#[inline(always)]
pub fn normalize_unchecked(self) -> Self {
let norm_squared = self.norm_squared();
self * norm_squared.sqrt_reciprocal()
}
#[inline(always)]
pub fn normalize_unchecked_in_place(&mut self) -> &mut Self {
*self = self.normalize_unchecked();
self
}
}
impl<T> Vector2d<T>
where
T: Copy + Vector2dMath,
{
#[inline(always)]
pub fn is_normalized(self) -> bool {
T::v2_is_normalized(self)
}
}
impl<T> Vector2d<T>
where
T: Copy + Zero + SqrtMethods + Vector2dMath,
{
#[inline(always)]
pub fn distance(self, other: Self) -> T {
self.distance_squared(other).sqrt()
}
}
impl<T> Vector2d<T>
where
T: Copy + Mul<Output = T> + MathConstants,
{
#[inline(always)]
pub fn to_degrees(self) -> Self {
Self { x: self.x * T::RADIANS_TO_DEGREES, y: self.y * T::RADIANS_TO_DEGREES }
}
#[inline(always)]
pub fn to_radians(self) -> Self {
Self { x: self.x * T::DEGREES_TO_RADIANS, y: self.y * T::DEGREES_TO_RADIANS }
}
}
impl<T> Vector2d<T>
where
T: Copy + Add<Output = T> + Sub<Output = T> + Mul<Output = T>,
{
#[inline(always)]
pub fn sum(self) -> T {
self.x + self.y
}
#[inline(always)]
pub fn product(self) -> T {
self.x * self.y
}
}
impl<T> Vector2d<T>
where
T: Copy + One + Add<Output = T> + Div<Output = T>,
{
#[inline(always)]
pub fn mean(self) -> T {
(self.x + self.y) / (T::one() + T::one())
}
}
impl<T> Vector2d<T>
where
T: Copy + Vector2dMath,
{
#[inline(always)]
pub fn max(self) -> T {
T::v2_max(self)
}
#[inline(always)]
pub fn min(self) -> T {
T::v2_min(self)
}
}
impl<T> From<(T, T)> for Vector2d<T> {
#[inline(always)]
fn from((x, y): (T, T)) -> Self {
Self { x, y }
}
}
impl<T> From<[T; 2]> for Vector2d<T>
where
T: Copy,
{
#[inline(always)]
fn from(v: [T; 2]) -> Self {
Self { x: v[0], y: v[1] }
}
}
impl<T> From<Vector2d<T>> for [T; 2] {
#[inline(always)]
fn from(v: Vector2d<T>) -> Self {
[v.x, v.y]
}
}