use pathfinder_simd::default::{F32x2, F32x4, I32x2};
use std::hash::{Hash, Hasher};
use std::ops::{Add, AddAssign, Div, Mul, MulAssign, Neg, Sub, SubAssign};
#[derive(Clone, Copy, Debug, Default)]
pub struct Vector2F(pub F32x2);
impl Vector2F {
#[inline]
pub fn new(x: f32, y: f32) -> Vector2F {
Vector2F(F32x2::new(x, y))
}
#[inline]
pub fn splat(value: f32) -> Vector2F {
Vector2F(F32x2::splat(value))
}
#[inline]
pub fn zero() -> Vector2F {
Vector2F::default()
}
#[inline]
pub fn to_3d(self) -> Vector3F {
Vector3F(self.0.to_f32x4().concat_xy_zw(F32x4::new(0.0, 0.0, 0.0, 0.0)))
}
#[inline]
pub fn to_4d(self) -> Vector4F {
Vector4F(self.0.to_f32x4().concat_xy_zw(F32x4::new(0.0, 0.0, 0.0, 1.0)))
}
#[inline]
pub fn x(self) -> f32 {
self.0[0]
}
#[inline]
pub fn y(self) -> f32 {
self.0[1]
}
#[inline]
pub fn set_x(&mut self, x: f32) {
self.0[0] = x;
}
#[inline]
pub fn set_y(&mut self, y: f32) {
self.0[1] = y;
}
#[inline]
pub fn min(self, other: Vector2F) -> Vector2F {
Vector2F(self.0.min(other.0))
}
#[inline]
pub fn max(self, other: Vector2F) -> Vector2F {
Vector2F(self.0.max(other.0))
}
#[inline]
pub fn clamp(self, min_val: Vector2F, max_val: Vector2F) -> Vector2F {
self.max(min_val).min(max_val)
}
#[inline]
pub fn det(self, other: Vector2F) -> f32 {
self.x() * other.y() - self.y() * other.x()
}
#[inline]
pub fn dot(self, other: Vector2F) -> f32 {
let xy = self.0 * other.0;
xy.x() + xy.y()
}
#[inline]
pub fn floor(self) -> Vector2F {
Vector2F(self.0.floor())
}
#[inline]
pub fn ceil(self) -> Vector2F {
Vector2F(self.0.ceil())
}
#[inline]
pub fn round(self) -> Vector2F {
Vector2F(self.0.to_i32x2().to_f32x2())
}
#[inline]
pub fn square_length(self) -> f32 {
let squared = self.0 * self.0;
squared[0] + squared[1]
}
#[inline]
pub fn length(self) -> f32 {
f32::sqrt(self.square_length())
}
#[inline]
pub fn normalize(self) -> Vector2F {
self * (1.0 / self.length())
}
#[inline]
pub fn yx(self) -> Vector2F {
Vector2F(self.0.yx())
}
#[inline]
pub fn projection_coefficient(self, a: Vector2F) -> f32 {
a.dot(self) / self.square_length()
}
#[inline]
pub fn is_zero(self) -> bool {
self == Vector2F::zero()
}
#[inline]
pub fn lerp(self, other: Vector2F, t: f32) -> Vector2F {
self + (other - self) * t
}
#[inline]
pub fn to_i32(self) -> Vector2I {
Vector2I(self.0.to_i32x2())
}
}
#[inline]
pub fn vec2f(x: f32, y: f32) -> Vector2F {
Vector2F::new(x, y)
}
impl PartialEq for Vector2F {
#[inline]
fn eq(&self, other: &Vector2F) -> bool {
self.0.packed_eq(other.0).all_true()
}
}
impl Add<Vector2F> for Vector2F {
type Output = Vector2F;
#[inline]
fn add(self, other: Vector2F) -> Vector2F {
Vector2F(self.0 + other.0)
}
}
impl Add<f32> for Vector2F {
type Output = Vector2F;
#[inline]
fn add(self, other: f32) -> Vector2F {
self + Vector2F::splat(other)
}
}
impl AddAssign<Vector2F> for Vector2F {
#[inline]
fn add_assign(&mut self, other: Vector2F) {
*self = *self + other
}
}
impl Sub<Vector2F> for Vector2F {
type Output = Vector2F;
#[inline]
fn sub(self, other: Vector2F) -> Vector2F {
Vector2F(self.0 - other.0)
}
}
impl Sub<f32> for Vector2F {
type Output = Vector2F;
#[inline]
fn sub(self, other: f32) -> Vector2F {
self - Vector2F::splat(other)
}
}
impl SubAssign<Vector2F> for Vector2F {
#[inline]
fn sub_assign(&mut self, other: Vector2F) {
*self = *self - other
}
}
impl Mul<Vector2F> for Vector2F {
type Output = Vector2F;
#[inline]
fn mul(self, other: Vector2F) -> Vector2F {
Vector2F(self.0 * other.0)
}
}
impl Mul<f32> for Vector2F {
type Output = Vector2F;
#[inline]
fn mul(self, other: f32) -> Vector2F {
self * Vector2F::splat(other)
}
}
impl MulAssign<Vector2F> for Vector2F {
#[inline]
fn mul_assign(&mut self, other: Vector2F) {
*self = *self * other
}
}
impl MulAssign<f32> for Vector2F {
#[inline]
fn mul_assign(&mut self, other: f32) {
*self = *self * other
}
}
impl Div<Vector2F> for Vector2F {
type Output = Vector2F;
#[inline]
fn div(self, other: Vector2F) -> Vector2F {
Vector2F(self.0 / other.0)
}
}
impl Div<f32> for Vector2F {
type Output = Vector2F;
#[inline]
fn div(self, other: f32) -> Vector2F {
self / Vector2F::splat(other)
}
}
impl Neg for Vector2F {
type Output = Vector2F;
#[inline]
fn neg(self) -> Vector2F {
Vector2F(-self.0)
}
}
pub trait IntoVector2F {
fn into_vector_2f(self) -> Vector2F;
}
impl IntoVector2F for Vector2F {
#[inline]
fn into_vector_2f(self) -> Vector2F {
self
}
}
impl IntoVector2F for f32 {
#[inline]
fn into_vector_2f(self) -> Vector2F {
Vector2F::splat(self)
}
}
#[derive(Clone, Copy, Debug, Default)]
pub struct Vector2I(pub I32x2);
impl Vector2I {
#[inline]
pub fn new(x: i32, y: i32) -> Vector2I {
Vector2I(I32x2::new(x, y))
}
#[inline]
pub fn splat(value: i32) -> Vector2I {
Vector2I(I32x2::splat(value))
}
#[inline]
pub fn zero() -> Vector2I {
Vector2I::default()
}
#[inline]
pub fn x(self) -> i32 {
self.0[0]
}
#[inline]
pub fn y(self) -> i32 {
self.0[1]
}
#[inline]
pub fn set_x(&mut self, x: i32) {
self.0[0] = x;
}
#[inline]
pub fn set_y(&mut self, y: i32) {
self.0[1] = y;
}
#[inline]
pub fn min(self, other: Vector2I) -> Vector2I {
Vector2I(self.0.min(other.0))
}
#[inline]
pub fn max(self, other: Vector2I) -> Vector2I {
Vector2I(self.0.max(other.0))
}
#[inline]
pub fn to_f32(self) -> Vector2F {
Vector2F(self.0.to_f32x2())
}
}
#[inline]
pub fn vec2i(x: i32, y: i32) -> Vector2I {
Vector2I::new(x, y)
}
impl Add<Vector2I> for Vector2I {
type Output = Vector2I;
#[inline]
fn add(self, other: Vector2I) -> Vector2I {
Vector2I(self.0 + other.0)
}
}
impl Add<i32> for Vector2I {
type Output = Vector2I;
#[inline]
fn add(self, other: i32) -> Vector2I {
self + Vector2I::splat(other)
}
}
impl AddAssign<Vector2I> for Vector2I {
#[inline]
fn add_assign(&mut self, other: Vector2I) {
self.0 += other.0
}
}
impl Neg for Vector2I {
type Output = Vector2I;
#[inline]
fn neg(self) -> Vector2I {
Vector2I(-self.0)
}
}
impl Sub<Vector2I> for Vector2I {
type Output = Vector2I;
#[inline]
fn sub(self, other: Vector2I) -> Vector2I {
Vector2I(self.0 - other.0)
}
}
impl Sub<i32> for Vector2I {
type Output = Vector2I;
#[inline]
fn sub(self, other: i32) -> Vector2I {
self - Vector2I::splat(other)
}
}
impl Mul<Vector2I> for Vector2I {
type Output = Vector2I;
#[inline]
fn mul(self, other: Vector2I) -> Vector2I {
Vector2I(self.0 * other.0)
}
}
impl Mul<i32> for Vector2I {
type Output = Vector2I;
#[inline]
fn mul(self, other: i32) -> Vector2I {
self * Vector2I::splat(other)
}
}
impl PartialEq for Vector2I {
#[inline]
fn eq(&self, other: &Vector2I) -> bool {
self.0.packed_eq(other.0).all_true()
}
}
impl Eq for Vector2I {}
impl Hash for Vector2I {
#[inline]
fn hash<H>(&self, state: &mut H) where H: Hasher {
self.x().hash(state);
self.y().hash(state);
}
}
#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct Vector3F(pub F32x4);
impl Vector3F {
#[inline]
pub fn new(x: f32, y: f32, z: f32) -> Vector3F {
Vector3F(F32x4::new(x, y, z, 0.0))
}
#[inline]
pub fn splat(x: f32) -> Vector3F {
let mut vector = F32x4::splat(x);
vector.set_w(0.0);
Vector3F(vector)
}
#[inline]
pub fn to_2d(self) -> Vector2F {
Vector2F(self.0.xy())
}
#[inline]
pub fn to_4d(self) -> Vector4F {
let mut vector = self.0;
vector.set_w(1.0);
Vector4F(vector)
}
#[inline]
pub fn cross(self, other: Vector3F) -> Vector3F {
Vector3F(self.0.yzxw() * other.0.zxyw() - self.0.zxyw() * other.0.yzxw())
}
#[inline]
pub fn square_length(self) -> f32 {
let squared = self.0 * self.0;
squared[0] + squared[1] + squared[2]
}
#[inline]
pub fn length(self) -> f32 {
f32::sqrt(self.square_length())
}
#[inline]
pub fn normalize(self) -> Vector3F {
Vector3F(self.0 * F32x4::splat(1.0 / self.length()))
}
#[inline]
pub fn x(self) -> f32 {
self.0[0]
}
#[inline]
pub fn y(self) -> f32 {
self.0[1]
}
#[inline]
pub fn z(self) -> f32 {
self.0[2]
}
#[inline]
pub fn scale(self, factor: f32) -> Vector3F {
Vector3F(self.0 * F32x4::splat(factor))
}
}
impl Add<Vector3F> for Vector3F {
type Output = Vector3F;
#[inline]
fn add(self, other: Vector3F) -> Vector3F {
Vector3F(self.0 + other.0)
}
}
impl AddAssign for Vector3F {
#[inline]
fn add_assign(&mut self, other: Vector3F) {
self.0 += other.0
}
}
impl Neg for Vector3F {
type Output = Vector3F;
#[inline]
fn neg(self) -> Vector3F {
Vector3F(self.0 * F32x4::new(-1.0, -1.0, -1.0, 0.0))
}
}
impl Sub<Vector3F> for Vector3F {
type Output = Vector3F;
#[inline]
fn sub(self, other: Vector3F) -> Vector3F {
Vector3F(self.0 - other.0)
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Vector4F(pub F32x4);
impl Vector4F {
#[inline]
pub fn new(x: f32, y: f32, z: f32, w: f32) -> Vector4F {
Vector4F(F32x4::new(x, y, z, w))
}
#[inline]
pub fn splat(value: f32) -> Vector4F {
Vector4F(F32x4::splat(value))
}
#[inline]
pub fn to_2d(self) -> Vector2F {
self.to_3d().to_2d()
}
#[inline]
pub fn to_3d(self) -> Vector3F {
let mut vector = self.0 * F32x4::splat(1.0 / self.w());
vector.set_w(0.0);
Vector3F(vector)
}
#[inline]
pub fn x(self) -> f32 {
self.0[0]
}
#[inline]
pub fn y(self) -> f32 {
self.0[1]
}
#[inline]
pub fn z(self) -> f32 {
self.0[2]
}
#[inline]
pub fn w(self) -> f32 {
self.0[3]
}
#[inline]
pub fn scale(self, x: f32) -> Vector4F {
let mut factors = F32x4::splat(x);
factors[3] = 1.0;
Vector4F(self.0 * factors)
}
#[inline]
pub fn set_x(&mut self, x: f32) {
self.0[0] = x
}
#[inline]
pub fn set_y(&mut self, y: f32) {
self.0[1] = y
}
#[inline]
pub fn set_z(&mut self, z: f32) {
self.0[2] = z
}
#[inline]
pub fn set_w(&mut self, w: f32) {
self.0[3] = w
}
#[inline]
pub fn approx_eq(self, other: Vector4F, epsilon: f32) -> bool {
self.0.approx_eq(other.0, epsilon)
}
#[inline]
pub fn is_zero(self) -> bool {
self.x() == 0.0 && self.y() == 0.0 && self.z() == 0.0
}
#[inline]
pub fn lerp(self, other: Vector4F, t: f32) -> Vector4F {
Vector4F(self.0 + (other.0 - self.0) * F32x4::splat(t))
}
}
impl Add<Vector4F> for Vector4F {
type Output = Vector4F;
#[inline]
fn add(self, other: Vector4F) -> Vector4F {
Vector4F(self.0 + other.0)
}
}
impl AddAssign for Vector4F {
#[inline]
fn add_assign(&mut self, other: Vector4F) {
self.0 += other.0
}
}
impl Mul<Vector4F> for Vector4F {
type Output = Vector4F;
#[inline]
fn mul(self, other: Vector4F) -> Vector4F {
Vector4F(self.0 * other.0)
}
}
impl Neg for Vector4F {
type Output = Vector4F;
#[inline]
fn neg(self) -> Vector4F {
Vector4F(self.0 * F32x4::new(-1.0, -1.0, -1.0, 1.0))
}
}
impl Sub<Vector4F> for Vector4F {
type Output = Vector4F;
#[inline]
fn sub(self, other: Vector4F) -> Vector4F {
Vector4F(self.0 - other.0)
}
}
impl Default for Vector4F {
#[inline]
fn default() -> Vector4F {
let mut point = F32x4::default();
point.set_w(1.0);
Vector4F(point)
}
}