use core::fmt;
use core::iter::{Product, Sum};
use core::ops::*;
use fidget::context::Tree;
use super::vec3::TreeVec3;
#[inline(always)]
#[must_use]
pub fn treevec2(x: Tree, y: Tree) -> TreeVec2 {
TreeVec2::new(x, y)
}
#[derive(Clone, PartialEq)]
pub struct TreeVec2 {
pub x: Tree,
pub y: Tree,
}
impl TreeVec2 {
#[inline(always)]
#[must_use]
pub fn new(x: impl Into<Tree>, y: impl Into<Tree>) -> Self {
Self {
x: x.into(),
y: y.into(),
}
}
#[inline]
#[must_use]
pub fn splat(v: impl Into<Tree> + Clone) -> Self {
Self {
x: v.clone().into(),
y: v.clone().into(),
}
}
#[inline]
#[must_use]
pub fn from_array(a: [impl Into<Tree> + Clone; 2]) -> Self {
Self::new(a[0].clone().into(), a[1].clone().into())
}
#[inline]
#[must_use]
pub fn to_array(&self) -> [Tree; 2] {
[self.x.clone(), self.y.clone()]
}
#[inline]
#[must_use]
pub fn from_slice(slice: &[impl Into<Tree> + Clone]) -> Self {
Self::new(slice[0].clone().into(), slice[1].clone().into())
}
#[inline]
pub fn write_to_slice(self, slice: &mut [Tree]) {
slice[0] = self.x;
slice[1] = self.y;
}
#[inline]
#[must_use]
pub fn extend(self, z: impl Into<Tree>) -> TreeVec3 {
TreeVec3::new(self.x, self.y, z.into())
}
#[inline]
#[must_use]
pub fn with_x(mut self, x: impl Into<Tree>) -> Self {
self.x = x.into();
self
}
#[inline]
#[must_use]
pub fn with_y(mut self, y: impl Into<Tree>) -> Self {
self.y = y.into();
self
}
#[inline]
#[must_use]
pub fn dot(self, rhs: Self) -> Tree {
(self.x * rhs.x) + (self.y * rhs.y)
}
#[inline]
#[must_use]
pub fn dot_into_vec(self, rhs: Self) -> Self {
Self::splat(self.dot(rhs))
}
#[inline]
#[must_use]
pub fn min(self, rhs: Self) -> Self {
Self {
x: self.x.min(rhs.x),
y: self.y.min(rhs.y),
}
}
#[inline]
#[must_use]
pub fn max(self, rhs: Self) -> Self {
Self {
x: self.x.max(rhs.x),
y: self.y.max(rhs.y),
}
}
#[inline]
#[must_use]
pub fn clamp(self, min: Self, max: Self) -> Self {
self.max(min).min(max)
}
#[inline]
#[must_use]
pub fn min_element(self) -> Tree {
self.x.min(self.y)
}
#[inline]
#[must_use]
pub fn max_element(self) -> Tree {
self.x.max(self.y)
}
#[inline]
#[must_use]
pub fn element_sum(self) -> Tree {
self.x + self.y
}
#[inline]
#[must_use]
pub fn element_product(self) -> Tree {
self.x * self.y
}
#[inline]
#[must_use]
pub fn abs(self) -> Self {
Self {
x: self.x.abs(),
y: self.y.abs(),
}
}
#[doc(alias = "magnitude")]
#[inline]
#[must_use]
pub fn length(self) -> Tree {
self.clone().dot(self).sqrt()
}
#[doc(alias = "magnitude2")]
#[inline]
#[must_use]
pub fn length_squared(self) -> Tree {
self.clone().dot(self)
}
#[inline]
#[must_use]
pub fn length_recip(self) -> Tree {
Tree::constant(1.0) / self.length()
}
#[inline]
#[must_use]
pub fn distance(self, rhs: Self) -> Tree {
(self - rhs).length()
}
#[inline]
#[must_use]
pub fn distance_squared(self, rhs: Self) -> Tree {
(self - rhs).length_squared()
}
#[inline]
#[must_use]
pub fn normalize(self) -> Self {
#[allow(clippy::let_and_return)]
let normalized = self.clone().mul(self.length_recip());
normalized
}
#[inline]
#[must_use]
pub fn project_onto(self, rhs: Self) -> Self {
let other_len_sq_rcp = Tree::constant(1.0) / rhs.clone().dot(rhs.clone());
rhs.clone() * self.dot(rhs) * other_len_sq_rcp
}
#[inline]
#[must_use]
pub fn reject_from(self, rhs: Self) -> Self {
self.clone() - self.project_onto(rhs)
}
#[inline]
#[must_use]
pub fn project_onto_normalized(self, rhs: Self) -> Self {
rhs.clone() * self.dot(rhs)
}
#[inline]
#[must_use]
pub fn reject_from_normalized(self, rhs: Self) -> Self {
self.clone() - self.project_onto_normalized(rhs)
}
#[inline]
#[must_use]
pub fn round(self) -> Self {
Self {
x: self.x.round(),
y: self.y.round(),
}
}
#[inline]
#[must_use]
pub fn floor(self) -> Self {
Self {
x: self.x.floor(),
y: self.y.floor(),
}
}
#[inline]
#[must_use]
pub fn ceil(self) -> Self {
Self {
x: self.x.ceil(),
y: self.y.ceil(),
}
}
#[inline]
#[must_use]
pub fn fract_gl(self) -> Self {
self.clone() - self.floor()
}
#[inline]
#[must_use]
pub fn exp(self) -> Self {
Self::new(self.x.exp(), self.y.exp())
}
#[inline]
#[must_use]
pub fn recip(self) -> Self {
Self {
x: Tree::constant(1.0) / self.x,
y: Tree::constant(1.0) / self.y,
}
}
#[doc(alias = "mix")]
#[inline]
#[must_use]
pub fn lerp(self, rhs: Self, s: impl Into<Tree>) -> Self {
self.clone() + ((rhs - self) * s.into())
}
#[inline]
pub fn midpoint(self, rhs: Self) -> Self {
(self + rhs) * Tree::constant(0.5)
}
#[inline]
#[must_use]
pub fn perp(self) -> Self {
Self {
x: self.y.neg(),
y: self.x,
}
}
#[doc(alias = "wedge")]
#[doc(alias = "cross")]
#[doc(alias = "determinant")]
#[inline]
#[must_use]
pub fn perp_dot(self, rhs: Self) -> Tree {
(self.x * rhs.y) - (self.y * rhs.x)
}
#[inline]
#[must_use]
pub fn rotate(self, rhs: Self) -> Self {
Self {
x: self.x.clone() * rhs.x.clone() - self.y.clone() * rhs.y.clone(),
y: self.y.clone() * rhs.x.clone() + self.x.clone() * rhs.y.clone(),
}
}
}
impl Default for TreeVec2 {
#[inline(always)]
fn default() -> Self {
Self::splat(Tree::constant(0.0))
}
}
impl Div<TreeVec2> for TreeVec2 {
type Output = Self;
#[inline]
fn div(self, rhs: Self) -> Self {
Self {
x: self.x.div(rhs.x),
y: self.y.div(rhs.y),
}
}
}
impl DivAssign<TreeVec2> for TreeVec2 {
#[inline]
fn div_assign(&mut self, rhs: Self) {
self.x.div_assign(rhs.x);
self.y.div_assign(rhs.y);
}
}
impl Div<Tree> for TreeVec2 {
type Output = Self;
#[inline]
fn div(self, rhs: Tree) -> Self {
Self {
x: self.x.div(rhs.clone()),
y: self.y.div(rhs.clone()),
}
}
}
impl DivAssign<Tree> for TreeVec2 {
#[inline]
fn div_assign(&mut self, rhs: Tree) {
self.x.div_assign(rhs.clone());
self.y.div_assign(rhs.clone());
}
}
impl Div<TreeVec2> for Tree {
type Output = TreeVec2;
#[inline]
fn div(self, rhs: TreeVec2) -> TreeVec2 {
TreeVec2 {
x: self.clone().div(rhs.x),
y: self.clone().div(rhs.y),
}
}
}
impl Mul<TreeVec2> for TreeVec2 {
type Output = Self;
#[inline]
fn mul(self, rhs: Self) -> Self {
Self {
x: self.x.mul(rhs.x),
y: self.y.mul(rhs.y),
}
}
}
impl MulAssign<TreeVec2> for TreeVec2 {
#[inline]
fn mul_assign(&mut self, rhs: Self) {
self.x.mul_assign(rhs.x);
self.y.mul_assign(rhs.y);
}
}
impl Mul<Tree> for TreeVec2 {
type Output = Self;
#[inline]
fn mul(self, rhs: Tree) -> Self {
Self {
x: self.x.mul(rhs.clone()),
y: self.y.mul(rhs.clone()),
}
}
}
impl MulAssign<Tree> for TreeVec2 {
#[inline]
fn mul_assign(&mut self, rhs: Tree) {
self.x.mul_assign(rhs.clone());
self.y.mul_assign(rhs.clone());
}
}
impl Mul<TreeVec2> for Tree {
type Output = TreeVec2;
#[inline]
fn mul(self, rhs: TreeVec2) -> TreeVec2 {
TreeVec2 {
x: self.clone().mul(rhs.x),
y: self.clone().mul(rhs.y),
}
}
}
impl Add<TreeVec2> for TreeVec2 {
type Output = Self;
#[inline]
fn add(self, rhs: Self) -> Self {
Self {
x: self.x.add(rhs.x),
y: self.y.add(rhs.y),
}
}
}
impl AddAssign<TreeVec2> for TreeVec2 {
#[inline]
fn add_assign(&mut self, rhs: Self) {
self.x.add_assign(rhs.x);
self.y.add_assign(rhs.y);
}
}
impl Add<Tree> for TreeVec2 {
type Output = Self;
#[inline]
fn add(self, rhs: Tree) -> Self {
Self {
x: self.x.add(rhs.clone()),
y: self.y.add(rhs.clone()),
}
}
}
impl AddAssign<Tree> for TreeVec2 {
#[inline]
fn add_assign(&mut self, rhs: Tree) {
self.x.add_assign(rhs.clone());
self.y.add_assign(rhs.clone());
}
}
impl Add<TreeVec2> for Tree {
type Output = TreeVec2;
#[inline]
fn add(self, rhs: TreeVec2) -> TreeVec2 {
TreeVec2 {
x: self.clone().add(rhs.x),
y: self.clone().add(rhs.y),
}
}
}
impl Sub<TreeVec2> for TreeVec2 {
type Output = Self;
#[inline]
fn sub(self, rhs: Self) -> Self {
Self {
x: self.x.sub(rhs.x),
y: self.y.sub(rhs.y),
}
}
}
impl SubAssign<TreeVec2> for TreeVec2 {
#[inline]
fn sub_assign(&mut self, rhs: TreeVec2) {
self.x.sub_assign(rhs.x);
self.y.sub_assign(rhs.y);
}
}
impl Sub<Tree> for TreeVec2 {
type Output = Self;
#[inline]
fn sub(self, rhs: Tree) -> Self {
Self {
x: self.x.sub(rhs.clone()),
y: self.y.sub(rhs.clone()),
}
}
}
impl SubAssign<Tree> for TreeVec2 {
#[inline]
fn sub_assign(&mut self, rhs: Tree) {
self.x.sub_assign(rhs.clone());
self.y.sub_assign(rhs.clone());
}
}
impl Sub<TreeVec2> for Tree {
type Output = TreeVec2;
#[inline]
fn sub(self, rhs: TreeVec2) -> TreeVec2 {
TreeVec2 {
x: self.clone().sub(rhs.x),
y: self.clone().sub(rhs.y),
}
}
}
impl Rem<TreeVec2> for TreeVec2 {
type Output = Self;
#[inline]
fn rem(self, rhs: Self) -> Self {
Self {
x: self.x.modulo(rhs.x),
y: self.y.modulo(rhs.y),
}
}
}
impl RemAssign<TreeVec2> for TreeVec2 {
#[inline]
fn rem_assign(&mut self, rhs: Self) {
self.x = self.x.modulo(rhs.x);
self.y = self.y.modulo(rhs.y);
}
}
impl Rem<Tree> for TreeVec2 {
type Output = Self;
#[inline]
fn rem(self, rhs: Tree) -> Self {
Self {
x: self.x.modulo(rhs.clone()),
y: self.y.modulo(rhs.clone()),
}
}
}
impl RemAssign<Tree> for TreeVec2 {
#[inline]
fn rem_assign(&mut self, rhs: Tree) {
self.x = self.x.modulo(rhs.clone());
self.y = self.y.modulo(rhs.clone());
}
}
impl Rem<TreeVec2> for Tree {
type Output = TreeVec2;
#[inline]
fn rem(self, rhs: TreeVec2) -> TreeVec2 {
TreeVec2 {
x: self.clone().modulo(rhs.x),
y: self.clone().modulo(rhs.y),
}
}
}
impl AsRef<[Tree; 2]> for TreeVec2 {
#[inline]
fn as_ref(&self) -> &[Tree; 2] {
unsafe { &*(self as *const TreeVec2 as *const [Tree; 2]) }
}
}
impl AsMut<[Tree; 2]> for TreeVec2 {
#[inline]
fn as_mut(&mut self) -> &mut [Tree; 2] {
unsafe { &mut *(self as *mut TreeVec2 as *mut [Tree; 2]) }
}
}
impl Sum for TreeVec2 {
#[inline]
fn sum<I>(iter: I) -> Self
where
I: Iterator<Item = Self>,
{
iter.fold(Self::splat(Tree::constant(0.0)), Self::add)
}
}
impl<'a> Sum<&'a Self> for TreeVec2 {
#[inline]
fn sum<I>(iter: I) -> Self
where
I: Iterator<Item = &'a Self>,
{
iter.fold(Self::splat(Tree::constant(0.0)), |a, b| {
Self::add(a, b.clone())
})
}
}
impl Product for TreeVec2 {
#[inline]
fn product<I>(iter: I) -> Self
where
I: Iterator<Item = Self>,
{
iter.fold(Self::splat(Tree::constant(1.0)), Self::mul)
}
}
impl<'a> Product<&'a Self> for TreeVec2 {
#[inline]
fn product<I>(iter: I) -> Self
where
I: Iterator<Item = &'a Self>,
{
iter.fold(Self::splat(Tree::constant(1.0)), |a, b| {
Self::mul(a, b.clone())
})
}
}
impl Neg for TreeVec2 {
type Output = Self;
#[inline]
fn neg(self) -> Self {
Self {
x: self.x.neg(),
y: self.y.neg(),
}
}
}
impl Index<usize> for TreeVec2 {
type Output = Tree;
#[inline]
fn index(&self, index: usize) -> &Self::Output {
match index {
0 => &self.x,
1 => &self.y,
_ => panic!("index out of bounds"),
}
}
}
impl IndexMut<usize> for TreeVec2 {
#[inline]
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
match index {
0 => &mut self.x,
1 => &mut self.y,
_ => panic!("index out of bounds"),
}
}
}
impl fmt::Debug for TreeVec2 {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_tuple(stringify!(TreeVec2))
.field(&self.x)
.field(&self.y)
.finish()
}
}
impl From<[Tree; 2]> for TreeVec2 {
#[inline]
fn from(a: [Tree; 2]) -> Self {
Self::new(a[0].clone(), a[1].clone())
}
}
impl From<TreeVec2> for [Tree; 2] {
#[inline]
fn from(v: TreeVec2) -> Self {
[v.x, v.y]
}
}
impl From<(Tree, Tree)> for TreeVec2 {
#[inline]
fn from(t: (Tree, Tree)) -> Self {
Self::new(t.0, t.1)
}
}
impl From<TreeVec2> for (Tree, Tree) {
#[inline]
fn from(v: TreeVec2) -> Self {
(v.x, v.y)
}
}