use crate::linear::scalar::Scalar;
use crate::numeric::float::Float;
use crate::numeric::identity::{One, Zero};
use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
#[repr(C)]
#[derive(Debug, Default, Copy, Clone)]
pub struct Bivector2<T> {
pub data: T,
}
impl<T> Bivector2<T> {
pub const fn new(data: T) -> Self {
Self { data }
}
#[inline]
pub fn layout() -> std::alloc::Layout {
std::alloc::Layout::from_size_align(std::mem::size_of::<Self>(), std::mem::align_of::<T>())
.unwrap()
}
#[inline]
pub fn as_slice(&self) -> &[T] {
unsafe { std::slice::from_raw_parts(self as *const Self as *const T, 1) }
}
#[inline]
pub fn as_mut_slice(&mut self) -> &mut [T] {
unsafe { std::slice::from_raw_parts_mut(self as *mut Self as *mut T, 1) }
}
#[inline]
pub fn as_byte_slice(&self) -> &[u8] {
unsafe {
std::slice::from_raw_parts(self as *const Self as *const u8, std::mem::size_of::<T>())
}
}
#[inline]
pub fn as_mut_byte_slice(&mut self) -> &mut [u8] {
unsafe {
std::slice::from_raw_parts_mut(self as *mut Self as *mut u8, std::mem::size_of::<T>())
}
}
#[inline]
pub const fn as_ptr(&self) -> *const T {
self as *const Self as *const T
}
#[inline]
pub fn as_mut_ptr(&mut self) -> *mut T {
self as *mut Self as *mut T
}
}
impl<T: Scalar> Bivector2<T> {
pub fn dot(self, rhs: Self) -> T {
self.data * rhs.data
}
}
impl<T: Scalar + Float> Bivector2<T> {
pub fn magnitude_squared(&self) -> T {
self.data * self.data
}
pub fn magnitude(&self) -> T {
self.magnitude_squared().sqrt()
}
pub fn normalize(&mut self) {
let mag = self.magnitude();
self.data /= mag;
}
pub fn normalized(&self) -> Self {
let mut bivec = *self;
bivec.normalize();
bivec
}
}
impl<T: Scalar> Add for Bivector2<T> {
type Output = Self;
#[inline]
fn add(mut self, rhs: Bivector2<T>) -> Self {
self += rhs;
self
}
}
impl<T: Scalar> AddAssign for Bivector2<T> {
#[inline]
fn add_assign(&mut self, rhs: Bivector2<T>) {
self.data += rhs.data;
}
}
impl<T: Scalar> Sub for Bivector2<T> {
type Output = Self;
#[inline]
fn sub(mut self, rhs: Bivector2<T>) -> Self {
self -= rhs;
self
}
}
impl<T: Scalar> SubAssign for Bivector2<T> {
#[inline]
fn sub_assign(&mut self, rhs: Bivector2<T>) {
self.data -= rhs.data;
}
}
impl<T: Scalar> Mul for Bivector2<T> {
type Output = Self;
#[inline]
fn mul(mut self, rhs: Bivector2<T>) -> Self {
self *= rhs;
self
}
}
impl<T: Scalar> Mul<T> for Bivector2<T> {
type Output = Self;
#[inline]
fn mul(mut self, rhs: T) -> Self {
self *= rhs;
self
}
}
impl<T: Scalar> MulAssign for Bivector2<T> {
#[inline]
fn mul_assign(&mut self, rhs: Self) {
self.data *= rhs.data;
}
}
impl<T: Scalar> MulAssign<T> for Bivector2<T> {
#[inline]
fn mul_assign(&mut self, rhs: T) {
self.data *= rhs;
}
}
impl<T: Scalar> Div for Bivector2<T> {
type Output = Self;
#[inline]
fn div(mut self, rhs: Bivector2<T>) -> Self {
self /= rhs;
self
}
}
impl<T: Scalar> Div<T> for Bivector2<T> {
type Output = Bivector2<T>;
#[inline]
fn div(mut self, rhs: T) -> Bivector2<T> {
self.data /= rhs;
self
}
}
impl<T: Scalar> DivAssign for Bivector2<T> {
#[inline]
fn div_assign(&mut self, rhs: Self) {
self.data /= rhs.data;
}
}
impl<T: Scalar> DivAssign<T> for Bivector2<T> {
#[inline]
fn div_assign(&mut self, rhs: T) {
self.data /= rhs;
}
}
impl<T: Scalar> Neg for Bivector2<T> {
type Output = Self;
#[inline]
fn neg(mut self) -> Self {
self.data = -self.data;
self
}
}
impl<T: Scalar> Zero for Bivector2<T> {
fn zero() -> Self {
Self { data: <T>::zero() }
}
fn is_zero(&self) -> bool {
self.data == <T>::zero()
}
}
impl<T: Scalar> One for Bivector2<T> {
fn one() -> Self {
Self { data: <T>::one() }
}
fn is_one(&self) -> bool {
self.data == <T>::one()
}
}