//! Native vector and ray value types compatible with `LibreMetaverse`.

#![allow(clippy::cast_possible_truncation)] // Explicit C# numeric conversions are part of the API.
#![allow(clippy::float_cmp)] // Exact component equality is required by the reference types.
#![allow(clippy::inherent_to_string)] // The mapped C# methods are named ToString.
#![allow(clippy::many_single_char_names)] // Vector formulas use conventional component operands.
#![allow(clippy::missing_errors_doc)] // Result shapes are fixed by the public compatibility map.
#![allow(clippy::must_use_candidate)] // Attributes are not part of the mapped C# surface.
#![allow(clippy::needless_pass_by_value)] // Owned arguments mirror mapped C# value parameters.
#![allow(clippy::should_implement_trait)] // Operator entry points have fixed generated names.
#![allow(clippy::single_match_else)] // TryParse mirrors the reference success/failure branches.

use crate::byte_order::{
    read_double_little_endian, read_single_little_endian, write_double_little_endian,
    write_single_little_endian,
};
use crate::compat::Object;
use crate::math_compat::{
    clamp_f32, clamp_f64, compare_f32, compare_f64, format_f32, format_f64, hash_f32, hash_f64,
    lerp_f32, lerp_f64, max_f32, max_f64, min_f32, min_f64, parse_f32, parse_f64, smooth_step_f32,
    smooth_step_f64,
};
use crate::{Error, Matrix4, Quaternion};

#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct Vector2 {
    pub x: f32,
    pub y: f32,
}

impl Vector2 {
    #[must_use]
    pub const fn zero() -> Self {
        Self { x: 0.0, y: 0.0 }
    }
    #[must_use]
    pub const fn one() -> Self {
        Self { x: 1.0, y: 1.0 }
    }
    #[must_use]
    pub const fn unit_x() -> Self {
        Self { x: 1.0, y: 0.0 }
    }
    #[must_use]
    pub const fn unit_y() -> Self {
        Self { x: 0.0, y: 1.0 }
    }

    pub const fn new_with_vector2(vector: Self) -> Result<Self, Error> {
        Ok(vector)
    }
    pub const fn new_with_single(value: f32) -> Result<Self, Error> {
        Ok(Self { x: value, y: value })
    }
    pub const fn new_with_single_single(x: f32, y: f32) -> Result<Self, Error> {
        Ok(Self { x, y })
    }

    pub fn approx_equals(&mut self, vec: Self, tolerance: f32) -> Result<bool, Error> {
        Ok(Self::distance_squared(*self, vec)? <= tolerance * tolerance)
    }
    pub fn is_finite(&self) -> Result<bool, Error> {
        Ok(self.x.is_finite() && self.y.is_finite())
    }
    pub fn compare_to(&self, vector: Self) -> Result<i32, Error> {
        Ok(compare_f32(self.length_value(), vector.length_value()))
    }
    pub fn from_bytes(&mut self, byte_array: Vec<u8>, pos: i32) -> Result<(), Error> {
        self.x = read_single_little_endian(&byte_array, pos)?;
        self.y = read_single_little_endian(
            &byte_array,
            pos.checked_add(4).ok_or(Error::IndexOutOfRange)?,
        )?;
        Ok(())
    }
    pub fn get_bytes(&self) -> Result<Vec<u8>, Error> {
        let mut bytes = vec![0; 8];
        self.to_bytes(&mut bytes, 0)?;
        Ok(bytes)
    }
    pub fn to_bytes(&self, dest: &mut [u8], pos: i32) -> Result<(), Error> {
        write_single_little_endian(dest, pos, self.x)?;
        write_single_little_endian(
            dest,
            pos.checked_add(4).ok_or(Error::IndexOutOfRange)?,
            self.y,
        )
    }
    fn length_value(self) -> f32 {
        self.length_squared_value().sqrt()
    }
    fn length_squared_value(self) -> f32 {
        self.x * self.x + self.y * self.y
    }
    pub fn length(&mut self) -> Result<f32, Error> {
        Ok(self.length_value())
    }
    pub fn length_squared(&mut self) -> Result<f32, Error> {
        Ok(self.length_squared_value())
    }
    pub fn normalize_with_method(&mut self) -> Result<(), Error> {
        *self = Self::normalize_value(*self);
        Ok(())
    }

    pub fn add_with_vector2_vector2(value1: Self, value2: Self) -> Result<Self, Error> {
        Ok(Self::add_value(value1, value2))
    }
    pub fn clamp(value1: Self, min: Self, max: Self) -> Result<Self, Error> {
        Ok(Self {
            x: clamp_f32(value1.x, min.x, max.x),
            y: clamp_f32(value1.y, min.y, max.y),
        })
    }
    pub fn distance(value1: Self, value2: Self) -> Result<f32, Error> {
        Ok(Self::distance_squared(value1, value2)?.sqrt())
    }
    pub fn distance_squared(value1: Self, value2: Self) -> Result<f32, Error> {
        let x = value1.x - value2.x;
        let y = value1.y - value2.y;
        Ok(x * x + y * y)
    }
    pub fn divide_with_vector2_vector2(value1: Self, value2: Self) -> Result<Self, Error> {
        Ok(Self::div_value(value1, value2))
    }
    pub fn divide_with_vector2_single(value1: Self, divider: f32) -> Result<Self, Error> {
        Ok(Self::div_scalar(value1, divider))
    }
    pub fn dot(value1: Self, value2: Self) -> Result<f32, Error> {
        Ok(value1.x * value2.x + value1.y * value2.y)
    }
    pub fn lerp(value1: Self, value2: Self, amount: f32) -> Result<Self, Error> {
        Ok(Self {
            x: lerp_f32(value1.x, value2.x, amount),
            y: lerp_f32(value1.y, value2.y, amount),
        })
    }
    pub fn max(value1: Self, value2: Self) -> Result<Self, Error> {
        Ok(Self {
            x: max_f32(value1.x, value2.x),
            y: max_f32(value1.y, value2.y),
        })
    }
    pub fn min(value1: Self, value2: Self) -> Result<Self, Error> {
        Ok(Self {
            x: min_f32(value1.x, value2.x),
            y: min_f32(value1.y, value2.y),
        })
    }
    pub fn multiply_with_vector2_vector2(value1: Self, value2: Self) -> Result<Self, Error> {
        Ok(Self::mul_value(value1, value2))
    }
    pub fn multiply_with_vector2_single(value1: Self, scale_factor: f32) -> Result<Self, Error> {
        Ok(Self::mul_scalar(value1, scale_factor))
    }
    pub fn negate(value: Self) -> Result<Self, Error> {
        Ok(Self::neg_value(value))
    }
    pub fn normalize_with_vector2(value: Self) -> Result<Self, Error> {
        Ok(Self::normalize_value(value))
    }
    pub fn smooth_step(value1: Self, value2: Self, amount: f32) -> Result<Self, Error> {
        Ok(Self {
            x: smooth_step_f32(value1.x, value2.x, amount),
            y: smooth_step_f32(value1.y, value2.y, amount),
        })
    }
    pub fn subtract(value1: Self, value2: Self) -> Result<Self, Error> {
        Ok(Self::sub_value(value1, value2))
    }

    fn normalize_value(mut value: Self) -> Self {
        let mut factor = value.length_squared_value();
        if factor > 0.000_000_1 {
            factor = 1.0 / factor.sqrt();
            value.x *= factor;
            value.y *= factor;
        } else {
            value = Self::zero();
        }
        value
    }
    fn add_value(mut lhs: Self, rhs: Self) -> Self {
        lhs.x += rhs.x;
        lhs.y += rhs.y;
        lhs
    }
    fn sub_value(mut lhs: Self, rhs: Self) -> Self {
        lhs.x -= rhs.x;
        lhs.y -= rhs.y;
        lhs
    }
    fn mul_value(mut lhs: Self, rhs: Self) -> Self {
        lhs.x *= rhs.x;
        lhs.y *= rhs.y;
        lhs
    }
    fn mul_scalar(mut value: Self, factor: f32) -> Self {
        value.x *= factor;
        value.y *= factor;
        value
    }
    fn div_value(mut lhs: Self, rhs: Self) -> Self {
        lhs.x /= rhs.x;
        lhs.y /= rhs.y;
        lhs
    }
    fn div_scalar(mut value: Self, divider: f32) -> Self {
        let factor = 1.0 / divider;
        value.x *= factor;
        value.y *= factor;
        value
    }
    fn neg_value(value: Self) -> Self {
        Self {
            x: -value.x,
            y: -value.y,
        }
    }

    pub fn parse(val: String) -> Result<Self, Error> {
        let trimmed = val.trim();
        let trimmed = if trimmed.len() >= 2 && trimmed.starts_with('<') && trimmed.ends_with('>') {
            &trimmed[1..trimmed.len() - 1]
        } else {
            trimmed
        };
        let split: Vec<_> = trimmed.split(',').collect();
        if split.len() != 2 {
            return Err(Error::Argument);
        }
        Ok(Self {
            x: parse_f32(split[0])?,
            y: parse_f32(split[1])?,
        })
    }
    pub fn try_parse(val: String, result: &mut Self) -> bool {
        match Self::parse(val) {
            Ok(value) => {
                *result = value;
                true
            }
            Err(_) => {
                *result = Self::zero();
                false
            }
        }
    }
    pub fn transform(mut position: Self, matrix: Matrix4) -> Result<Self, Error> {
        position.x = position.x * matrix.m11 + position.y * matrix.m21 + matrix.m41;
        position.y = position.x * matrix.m12 + position.y * matrix.m22 + matrix.m42;
        Ok(position)
    }
    pub fn transform_normal(mut position: Self, matrix: Matrix4) -> Result<Self, Error> {
        position.x = position.x * matrix.m11 + position.y * matrix.m21;
        position.y = position.x * matrix.m12 + position.y * matrix.m22;
        Ok(position)
    }
    pub fn equals_with_vector2(&self, other: Self) -> bool {
        Self::eq(*self, other)
    }
    pub fn equals_with_object(&self, obj: Option<Object>) -> bool {
        matches!(obj, Some(Object::Vector2(value)) if Self::eq(*self, value))
    }
    pub fn get_hash_code(&self) -> i32 {
        hash_f32(self.x)
            .wrapping_mul(31)
            .wrapping_add(hash_f32(self.y))
    }
    pub fn to_string(&self) -> String {
        format!("<{}, {}>", format_f32(self.x), format_f32(self.y))
    }
    pub fn to_raw_string(&self) -> Result<String, Error> {
        Ok(format!("{:.3} {:.3}", self.x, self.y))
    }

    pub fn eq(value1: Self, value2: Self) -> bool {
        value1.x == value2.x && value1.y == value2.y
    }
    pub fn ne(value1: Self, value2: Self) -> bool {
        !Self::eq(value1, value2)
    }
    pub fn add_with_vector2_vector2_97a2f1ee(value1: Self, value2: Self) -> Self {
        Self::add_value(value1, value2)
    }
    pub fn sub(value1: Self, value2: Self) -> Self {
        Self::sub_value(value1, value2)
    }
    pub fn mul_with_vector2_vector2(value1: Self, value2: Self) -> Self {
        Self::mul_value(value1, value2)
    }
    pub fn mul_with_vector2_single(value: Self, scale_factor: f32) -> Self {
        Self::mul_scalar(value, scale_factor)
    }
    pub fn div_with_vector2_vector2(value1: Self, value2: Self) -> Self {
        Self::div_value(value1, value2)
    }
    pub fn div_with_vector2_single(value1: Self, divider: f32) -> Self {
        Self::div_scalar(value1, divider)
    }
    pub fn neg(value: Self) -> Self {
        Self::neg_value(value)
    }
}

#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct Vector3 {
    pub x: f32,
    pub y: f32,
    pub z: f32,
}

impl Vector3 {
    #[must_use]
    pub const fn zero() -> Self {
        Self {
            x: 0.0,
            y: 0.0,
            z: 0.0,
        }
    }
    #[must_use]
    pub const fn one() -> Self {
        Self {
            x: 1.0,
            y: 1.0,
            z: 1.0,
        }
    }
    #[must_use]
    pub const fn unit_x() -> Self {
        Self {
            x: 1.0,
            y: 0.0,
            z: 0.0,
        }
    }
    #[must_use]
    pub const fn unit_y() -> Self {
        Self {
            x: 0.0,
            y: 1.0,
            z: 0.0,
        }
    }
    #[must_use]
    pub const fn unit_z() -> Self {
        Self {
            x: 0.0,
            y: 0.0,
            z: 1.0,
        }
    }

    pub const fn new_with_single_single_single(x: f32, y: f32, z: f32) -> Result<Self, Error> {
        Ok(Self { x, y, z })
    }
    pub const fn new_with_single(value: f32) -> Result<Self, Error> {
        Ok(Self {
            x: value,
            y: value,
            z: value,
        })
    }
    pub const fn new_with_vector2_single(value: Vector2, z: f32) -> Result<Self, Error> {
        Ok(Self {
            x: value.x,
            y: value.y,
            z,
        })
    }
    pub fn new_with_vector3d(vector: Vector3d) -> Result<Self, Error> {
        Ok(Self::try_from(vector))
    }
    pub fn new_with_bytes_int32(byte_array: Vec<u8>, pos: i32) -> Result<Self, Error> {
        Self::from_bytes(byte_array, pos)
    }

    fn length_squared_value(self) -> f32 {
        self.x * self.x + self.y * self.y + self.z * self.z
    }
    fn length_value(self) -> f32 {
        self.length_squared_value().sqrt()
    }
    pub fn length(&mut self) -> Result<f32, Error> {
        Ok(self.length_value())
    }
    pub fn length_squared(&mut self) -> Result<f32, Error> {
        Ok(self.length_squared_value())
    }
    pub fn approx_equals(&mut self, vec: Self, tolerance: f32) -> Result<bool, Error> {
        Ok(Self::distance_squared(*self, vec)? <= tolerance * tolerance)
    }
    pub fn compare_to(&self, vector: Self) -> Result<i32, Error> {
        Ok(compare_f32(self.length_value(), vector.length_value()))
    }
    pub fn is_finite(&self) -> Result<bool, Error> {
        Ok(self.x.is_finite() && self.y.is_finite() && self.z.is_finite())
    }
    pub fn from_bytes(byte_array: Vec<u8>, pos: i32) -> Result<Self, Error> {
        Ok(Self {
            x: read_single_little_endian(&byte_array, pos)?,
            y: read_single_little_endian(
                &byte_array,
                pos.checked_add(4).ok_or(Error::IndexOutOfRange)?,
            )?,
            z: read_single_little_endian(
                &byte_array,
                pos.checked_add(8).ok_or(Error::IndexOutOfRange)?,
            )?,
        })
    }
    pub fn get_bytes(&self) -> Result<Vec<u8>, Error> {
        let mut bytes = vec![0; 12];
        self.to_bytes(&mut bytes, 0)?;
        Ok(bytes)
    }
    pub fn to_bytes(&self, dest: &mut [u8], pos: i32) -> Result<(), Error> {
        write_single_little_endian(dest, pos, self.x)?;
        write_single_little_endian(
            dest,
            pos.checked_add(4).ok_or(Error::IndexOutOfRange)?,
            self.y,
        )?;
        write_single_little_endian(
            dest,
            pos.checked_add(8).ok_or(Error::IndexOutOfRange)?,
            self.z,
        )
    }

    fn add_value(value1: Self, value2: Self) -> Self {
        Self {
            x: value1.x + value2.x,
            y: value1.y + value2.y,
            z: value1.z + value2.z,
        }
    }
    fn sub_value(value1: Self, value2: Self) -> Self {
        Self {
            x: value1.x - value2.x,
            y: value1.y - value2.y,
            z: value1.z - value2.z,
        }
    }
    fn mul_value(value1: Self, value2: Self) -> Self {
        Self {
            x: value1.x * value2.x,
            y: value1.y * value2.y,
            z: value1.z * value2.z,
        }
    }
    fn mul_scalar(value: Self, factor: f32) -> Self {
        Self {
            x: value.x * factor,
            y: value.y * factor,
            z: value.z * factor,
        }
    }
    fn div_value(value1: Self, value2: Self) -> Self {
        Self {
            x: value1.x / value2.x,
            y: value1.y / value2.y,
            z: value1.z / value2.z,
        }
    }
    fn div_scalar(value: Self, divider: f32) -> Self {
        Self::mul_scalar(value, 1.0 / divider)
    }
    fn neg_value(value: Self) -> Self {
        Self {
            x: -value.x,
            y: -value.y,
            z: -value.z,
        }
    }
    fn cross_value(value1: Self, value2: Self) -> Self {
        Self {
            x: value1.y * value2.z - value2.y * value1.z,
            y: value1.z * value2.x - value2.z * value1.x,
            z: value1.x * value2.y - value2.x * value1.y,
        }
    }
    fn normalize_value(value: Self) -> Self {
        let length = value.length_value();
        if length > 0.000_000_1 {
            Self::mul_scalar(value, 1.0 / length)
        } else {
            Self::zero()
        }
    }

    pub fn add_with_vector3_vector3(value1: Self, value2: Self) -> Result<Self, Error> {
        Ok(Self::add_value(value1, value2))
    }
    pub fn clamp(value1: Self, min: Self, max: Self) -> Result<Self, Error> {
        Ok(Self {
            x: clamp_f32(value1.x, min.x, max.x),
            y: clamp_f32(value1.y, min.y, max.y),
            z: clamp_f32(value1.z, min.z, max.z),
        })
    }
    pub fn cross(value1: Self, value2: Self) -> Result<Self, Error> {
        Ok(Self::cross_value(value1, value2))
    }
    pub fn distance(value1: Self, value2: Self) -> Result<f32, Error> {
        Ok(Self::distance_squared(value1, value2)?.sqrt())
    }
    pub fn distance_squared(value1: Self, value2: Self) -> Result<f32, Error> {
        Ok(Self::sub_value(value1, value2).length_squared_value())
    }
    pub fn divide_with_vector3_vector3(value1: Self, value2: Self) -> Result<Self, Error> {
        Ok(Self::div_value(value1, value2))
    }
    pub fn divide_with_vector3_single(value1: Self, value2: f32) -> Result<Self, Error> {
        Ok(Self::div_scalar(value1, value2))
    }
    pub fn dot(value1: Self, value2: Self) -> Result<f32, Error> {
        Ok(value1.x * value2.x + value1.y * value2.y + value1.z * value2.z)
    }
    pub fn lerp(value1: Self, value2: Self, amount: f32) -> Result<Self, Error> {
        Ok(Self {
            x: lerp_f32(value1.x, value2.x, amount),
            y: lerp_f32(value1.y, value2.y, amount),
            z: lerp_f32(value1.z, value2.z, amount),
        })
    }
    pub fn mag(value: Self) -> Result<f32, Error> {
        Ok(value.length_value())
    }
    pub fn max(value1: Self, value2: Self) -> Result<Self, Error> {
        Ok(Self {
            x: max_f32(value1.x, value2.x),
            y: max_f32(value1.y, value2.y),
            z: max_f32(value1.z, value2.z),
        })
    }
    pub fn min(value1: Self, value2: Self) -> Result<Self, Error> {
        Ok(Self {
            x: min_f32(value1.x, value2.x),
            y: min_f32(value1.y, value2.y),
            z: min_f32(value1.z, value2.z),
        })
    }
    pub fn multiply_with_vector3_vector3(value1: Self, value2: Self) -> Result<Self, Error> {
        Ok(Self::mul_value(value1, value2))
    }
    pub fn multiply_with_vector3_single(value1: Self, scale_factor: f32) -> Result<Self, Error> {
        Ok(Self::mul_scalar(value1, scale_factor))
    }
    pub fn negate(value: Self) -> Result<Self, Error> {
        Ok(Self::neg_value(value))
    }
    pub fn normalize(value: Self) -> Result<Self, Error> {
        Ok(Self::normalize_value(value))
    }
    pub fn smooth_step(value1: Self, value2: Self, amount: f32) -> Result<Self, Error> {
        Ok(Self {
            x: smooth_step_f32(value1.x, value2.x, amount),
            y: smooth_step_f32(value1.y, value2.y, amount),
            z: smooth_step_f32(value1.z, value2.z, amount),
        })
    }
    pub fn subtract(value1: Self, value2: Self) -> Result<Self, Error> {
        Ok(Self::sub_value(value1, value2))
    }

    pub fn parse(val: String) -> Result<Self, Error> {
        let trimmed = val.trim();
        let trimmed = if trimmed.len() >= 2 && trimmed.starts_with('<') && trimmed.ends_with('>') {
            &trimmed[1..trimmed.len() - 1]
        } else {
            trimmed
        };
        let split: Vec<_> = trimmed.split(',').collect();
        if split.len() != 3 {
            return Err(Error::Argument);
        }
        Ok(Self {
            x: parse_f32(split[0])?,
            y: parse_f32(split[1])?,
            z: parse_f32(split[2])?,
        })
    }
    pub fn try_parse(val: String, result: &mut Self) -> bool {
        match Self::parse(val) {
            Ok(value) => {
                *result = value;
                true
            }
            Err(_) => {
                *result = Self::zero();
                false
            }
        }
    }
    pub fn rotation_between(a: Self, b: Self) -> Result<Quaternion, Error> {
        let dot = Self::dot(a, b)?;
        let cross = Self::cross_value(a, b);
        let angle = f64::from(dot / (a.length_value() * b.length_value())).acos();
        let axis = Self::normalize_value(cross);
        let sine = (angle / 2.0).sin() as f32;
        Ok(Quaternion {
            x: axis.x * sine,
            y: axis.y * sine,
            z: axis.z * sine,
            w: (angle / 2.0).cos() as f32,
        })
    }
    pub fn transform(position: Self, matrix: Matrix4) -> Result<Self, Error> {
        Ok(Self {
            x: position.x * matrix.m11
                + position.y * matrix.m21
                + position.z * matrix.m31
                + matrix.m41,
            y: position.x * matrix.m12
                + position.y * matrix.m22
                + position.z * matrix.m32
                + matrix.m42,
            z: position.x * matrix.m13
                + position.y * matrix.m23
                + position.z * matrix.m33
                + matrix.m43,
        })
    }
    pub fn transform_normal(position: Self, matrix: Matrix4) -> Result<Self, Error> {
        Ok(Self {
            x: position.x * matrix.m11 + position.y * matrix.m21 + position.z * matrix.m31,
            y: position.x * matrix.m12 + position.y * matrix.m22 + position.z * matrix.m32,
            z: position.x * matrix.m13 + position.y * matrix.m23 + position.z * matrix.m33,
        })
    }
    pub fn equals_with_vector3(&self, other: Self) -> bool {
        Self::eq(*self, other)
    }
    pub fn equals_with_object(&self, obj: Option<Object>) -> bool {
        matches!(obj, Some(Object::Vector3(value)) if Self::eq(*self, value))
    }
    pub fn get_hash_code(&self) -> i32 {
        hash_f32(self.x)
            .wrapping_mul(31)
            .wrapping_add(hash_f32(self.y))
            .wrapping_mul(31)
            .wrapping_add(hash_f32(self.z))
    }
    pub fn to_string(&self) -> String {
        format!(
            "<{}, {}, {}>",
            format_f32(self.x),
            format_f32(self.y),
            format_f32(self.z)
        )
    }
    pub fn to_raw_string(&self) -> Result<String, Error> {
        Ok(format!("{:.3} {:.3} {:.3}", self.x, self.y, self.z))
    }

    pub fn eq(value1: Self, value2: Self) -> bool {
        value1.x == value2.x && value1.y == value2.y && value1.z == value2.z
    }
    pub fn ne(value1: Self, value2: Self) -> bool {
        !Self::eq(value1, value2)
    }
    pub fn add_with_vector3_vector3_87e25eaf(value1: Self, value2: Self) -> Self {
        Self::add_value(value1, value2)
    }
    pub fn sub(value1: Self, value2: Self) -> Self {
        Self::sub_value(value1, value2)
    }
    pub fn mul_with_vector3_vector3(value1: Self, value2: Self) -> Self {
        Self::mul_value(value1, value2)
    }
    pub fn mul_with_vector3_single(value: Self, scale_factor: f32) -> Self {
        Self::mul_scalar(value, scale_factor)
    }
    pub fn div_with_vector3_vector3(value1: Self, value2: Self) -> Self {
        Self::div_value(value1, value2)
    }
    pub fn div_with_vector3_single(value: Self, divider: f32) -> Self {
        Self::div_scalar(value, divider)
    }
    pub fn neg(value: Self) -> Self {
        Self::neg_value(value)
    }
    pub fn rem(value1: Self, value2: Self) -> Self {
        Self::cross_value(value1, value2)
    }
    pub fn try_from(value: Vector3d) -> Self {
        Self {
            x: value.x as f32,
            y: value.y as f32,
            z: value.z as f32,
        }
    }
    pub fn mul_with_vector3_matrix4(vector: Self, matrix: Matrix4) -> Self {
        Self {
            x: vector.x * matrix.m11 + vector.y * matrix.m21 + vector.z * matrix.m31 + matrix.m41,
            y: vector.x * matrix.m12 + vector.y * matrix.m22 + vector.z * matrix.m32 + matrix.m42,
            z: vector.x * matrix.m13 + vector.y * matrix.m23 + vector.z * matrix.m33 + matrix.m43,
        }
    }
    pub fn mul_with_vector3_quaternion(vec: Self, rot: Quaternion) -> Self {
        let rw = -rot.x * vec.x - rot.y * vec.y - rot.z * vec.z;
        let rx = rot.w * vec.x + rot.y * vec.z - rot.z * vec.y;
        let ry = rot.w * vec.y + rot.z * vec.x - rot.x * vec.z;
        let rz = rot.w * vec.z + rot.x * vec.y - rot.y * vec.x;
        Self {
            x: -rw * rot.x + rx * rot.w - ry * rot.z + rz * rot.y,
            y: -rw * rot.y + ry * rot.w - rz * rot.x + rx * rot.z,
            z: -rw * rot.z + rz * rot.w - rx * rot.y + ry * rot.x,
        }
    }
}

#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct Vector3d {
    pub x: f64,
    pub y: f64,
    pub z: f64,
}

impl Vector3d {
    #[must_use]
    pub const fn zero() -> Self {
        Self {
            x: 0.0,
            y: 0.0,
            z: 0.0,
        }
    }
    // The reference declares One using the default constructor; preserve that observable value.
    #[must_use]
    pub const fn one() -> Self {
        Self::zero()
    }
    #[must_use]
    pub const fn unit_x() -> Self {
        Self {
            x: 1.0,
            y: 0.0,
            z: 0.0,
        }
    }
    #[must_use]
    pub const fn unit_y() -> Self {
        Self {
            x: 0.0,
            y: 1.0,
            z: 0.0,
        }
    }
    #[must_use]
    pub const fn unit_z() -> Self {
        Self {
            x: 0.0,
            y: 0.0,
            z: 1.0,
        }
    }

    pub const fn new_with_double_double_double(x: f64, y: f64, z: f64) -> Result<Self, Error> {
        Ok(Self { x, y, z })
    }
    pub const fn new_with_double(value: f64) -> Result<Self, Error> {
        Ok(Self {
            x: value,
            y: value,
            z: value,
        })
    }
    pub const fn new_with_vector3(vector: Vector3) -> Result<Self, Error> {
        Ok(Self::from(vector))
    }
    pub const fn new_with_vector3d(vector: Self) -> Result<Self, Error> {
        Ok(vector)
    }
    pub fn new_with_bytes_int32(byte_array: Vec<u8>, pos: i32) -> Result<Self, Error> {
        let mut value = Self::zero();
        value.from_bytes(byte_array, pos)?;
        Ok(value)
    }

    fn length_squared_value(self) -> f64 {
        self.x * self.x + self.y * self.y + self.z * self.z
    }
    fn length_value(self) -> f64 {
        self.length_squared_value().sqrt()
    }
    pub fn length(&mut self) -> Result<f64, Error> {
        Ok(self.length_value())
    }
    pub fn length_squared(&mut self) -> Result<f64, Error> {
        Ok(self.length_squared_value())
    }
    pub fn normalize_with_method(&mut self) -> Result<(), Error> {
        *self = Self::normalize_value(*self);
        Ok(())
    }
    pub fn approx_equals(&mut self, vec: Self, tolerance: f64) -> Result<bool, Error> {
        Ok(Self::distance_squared(*self, vec)? <= tolerance * tolerance)
    }
    pub fn compare_to(&self, vector: Self) -> Result<i32, Error> {
        Ok(compare_f64(self.length_value(), vector.length_value()))
    }
    pub fn is_finite(&self) -> Result<bool, Error> {
        Ok(self.x.is_finite() && self.y.is_finite() && self.z.is_finite())
    }
    pub fn from_bytes(&mut self, byte_array: Vec<u8>, pos: i32) -> Result<(), Error> {
        self.x = read_double_little_endian(&byte_array, pos)?;
        self.y = read_double_little_endian(
            &byte_array,
            pos.checked_add(8).ok_or(Error::IndexOutOfRange)?,
        )?;
        self.z = read_double_little_endian(
            &byte_array,
            pos.checked_add(16).ok_or(Error::IndexOutOfRange)?,
        )?;
        Ok(())
    }
    pub fn get_bytes(&self) -> Result<Vec<u8>, Error> {
        let mut bytes = vec![0; 24];
        self.to_bytes(&mut bytes, 0)?;
        Ok(bytes)
    }
    pub fn to_bytes(&self, dest: &mut [u8], pos: i32) -> Result<(), Error> {
        write_double_little_endian(dest, pos, self.x)?;
        write_double_little_endian(
            dest,
            pos.checked_add(8).ok_or(Error::IndexOutOfRange)?,
            self.y,
        )?;
        write_double_little_endian(
            dest,
            pos.checked_add(16).ok_or(Error::IndexOutOfRange)?,
            self.z,
        )
    }

    fn add_value(a: Self, b: Self) -> Self {
        Self {
            x: a.x + b.x,
            y: a.y + b.y,
            z: a.z + b.z,
        }
    }
    fn sub_value(a: Self, b: Self) -> Self {
        Self {
            x: a.x - b.x,
            y: a.y - b.y,
            z: a.z - b.z,
        }
    }
    fn mul_value(a: Self, b: Self) -> Self {
        Self {
            x: a.x * b.x,
            y: a.y * b.y,
            z: a.z * b.z,
        }
    }
    fn mul_scalar(a: Self, b: f64) -> Self {
        Self {
            x: a.x * b,
            y: a.y * b,
            z: a.z * b,
        }
    }
    fn div_value(a: Self, b: Self) -> Self {
        Self {
            x: a.x / b.x,
            y: a.y / b.y,
            z: a.z / b.z,
        }
    }
    fn div_scalar(a: Self, b: f64) -> Self {
        Self::mul_scalar(a, 1.0 / b)
    }
    fn neg_value(a: Self) -> Self {
        Self {
            x: -a.x,
            y: -a.y,
            z: -a.z,
        }
    }
    fn cross_value(a: Self, b: Self) -> Self {
        Self {
            x: a.y * b.z - b.y * a.z,
            y: a.z * b.x - b.z * a.x,
            z: a.x * b.y - b.x * a.y,
        }
    }
    fn normalize_value(value: Self) -> Self {
        let length = value.length_value();
        if length > f64::from_bits(1) {
            Self::mul_scalar(value, 1.0 / length)
        } else {
            Self::zero()
        }
    }

    pub fn add_with_vector3d_vector3d(a: Self, b: Self) -> Result<Self, Error> {
        Ok(Self::add_value(a, b))
    }
    pub fn clamp(value: Self, min: Self, max: Self) -> Result<Self, Error> {
        Ok(Self {
            x: clamp_f64(value.x, min.x, max.x),
            y: clamp_f64(value.y, min.y, max.y),
            z: clamp_f64(value.z, min.z, max.z),
        })
    }
    pub fn cross(a: Self, b: Self) -> Result<Self, Error> {
        Ok(Self::cross_value(a, b))
    }
    pub fn distance(a: Self, b: Self) -> Result<f64, Error> {
        Ok(Self::distance_squared(a, b)?.sqrt())
    }
    pub fn distance_squared(a: Self, b: Self) -> Result<f64, Error> {
        Ok(Self::sub_value(a, b).length_squared_value())
    }
    pub fn divide_with_vector3d_vector3d(a: Self, b: Self) -> Result<Self, Error> {
        Ok(Self::div_value(a, b))
    }
    pub fn divide_with_vector3d_double(a: Self, b: f64) -> Result<Self, Error> {
        Ok(Self::div_scalar(a, b))
    }
    pub fn dot(a: Self, b: Self) -> Result<f64, Error> {
        Ok(a.x * b.x + a.y * b.y + a.z * b.z)
    }
    pub fn lerp(a: Self, b: Self, amount: f64) -> Result<Self, Error> {
        Ok(Self {
            x: lerp_f64(a.x, b.x, amount),
            y: lerp_f64(a.y, b.y, amount),
            z: lerp_f64(a.z, b.z, amount),
        })
    }
    pub fn max(a: Self, b: Self) -> Result<Self, Error> {
        Ok(Self {
            x: max_f64(a.x, b.x),
            y: max_f64(a.y, b.y),
            z: max_f64(a.z, b.z),
        })
    }
    pub fn min(a: Self, b: Self) -> Result<Self, Error> {
        Ok(Self {
            x: min_f64(a.x, b.x),
            y: min_f64(a.y, b.y),
            z: min_f64(a.z, b.z),
        })
    }
    pub fn multiply_with_vector3d_vector3d(a: Self, b: Self) -> Result<Self, Error> {
        Ok(Self::mul_value(a, b))
    }
    pub fn multiply_with_vector3d_double(a: Self, factor: f64) -> Result<Self, Error> {
        Ok(Self::mul_scalar(a, factor))
    }
    pub fn negate(value: Self) -> Result<Self, Error> {
        Ok(Self::neg_value(value))
    }
    pub fn normalize_with_vector3d(value: Self) -> Result<Self, Error> {
        Ok(Self::normalize_value(value))
    }
    pub fn smooth_step(a: Self, b: Self, amount: f64) -> Result<Self, Error> {
        Ok(Self {
            x: smooth_step_f64(a.x, b.x, amount),
            y: smooth_step_f64(a.y, b.y, amount),
            z: smooth_step_f64(a.z, b.z, amount),
        })
    }
    pub fn subtract(a: Self, b: Self) -> Result<Self, Error> {
        Ok(Self::sub_value(a, b))
    }

    pub fn parse(val: String) -> Result<Self, Error> {
        let stripped = val.replace(['<', '>'], "");
        let split: Vec<_> = stripped.split(',').collect();
        if split.len() < 3 {
            return Err(Error::Argument);
        }
        Ok(Self {
            x: parse_f64(split[0])?,
            y: parse_f64(split[1])?,
            z: parse_f64(split[2])?,
        })
    }
    pub fn try_parse(val: String, result: &mut Self) -> bool {
        match Self::parse(val) {
            Ok(value) => {
                *result = value;
                true
            }
            Err(_) => {
                *result = Self::zero();
                false
            }
        }
    }
    pub fn equals_with_vector3d(&self, other: Self) -> bool {
        Self::eq(*self, other)
    }
    pub fn equals_with_object(&self, obj: Option<Object>) -> bool {
        matches!(obj, Some(Object::Vector3d(value)) if Self::eq(*self, value))
    }
    pub fn get_hash_code(&self) -> i32 {
        hash_f64(self.x) ^ hash_f64(self.y) ^ hash_f64(self.z)
    }
    pub fn to_string(&self) -> String {
        format!(
            "<{}, {}, {}>",
            format_f64(self.x),
            format_f64(self.y),
            format_f64(self.z)
        )
    }
    pub fn to_raw_string(&self) -> Result<String, Error> {
        Ok(format!(
            "{} {} {}",
            format_f64(self.x),
            format_f64(self.y),
            format_f64(self.z)
        ))
    }

    pub fn eq(a: Self, b: Self) -> bool {
        a.x == b.x && a.y == b.y && a.z == b.z
    }
    pub fn ne(a: Self, b: Self) -> bool {
        !Self::eq(a, b)
    }
    pub fn add_with_vector3d_vector3d_bdf7d5f9(a: Self, b: Self) -> Self {
        Self::add_value(a, b)
    }
    pub fn sub(a: Self, b: Self) -> Self {
        Self::sub_value(a, b)
    }
    pub fn mul_with_vector3d_vector3d(a: Self, b: Self) -> Self {
        Self::mul_value(a, b)
    }
    pub fn mul_with_vector3d_double(a: Self, factor: f64) -> Self {
        Self::mul_scalar(a, factor)
    }
    pub fn div_with_vector3d_vector3d(a: Self, b: Self) -> Self {
        Self::div_value(a, b)
    }
    pub fn div_with_vector3d_double(a: Self, divider: f64) -> Self {
        Self::div_scalar(a, divider)
    }
    pub fn neg(value: Self) -> Self {
        Self::neg_value(value)
    }
    pub fn rem(a: Self, b: Self) -> Self {
        Self::cross_value(a, b)
    }
    pub const fn from(value: Vector3) -> Self {
        Self {
            x: value.x as f64,
            y: value.y as f64,
            z: value.z as f64,
        }
    }
}

impl From<Vector3> for Vector3d {
    fn from(value: Vector3) -> Self {
        Self::from(value)
    }
}

#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct Vector4 {
    pub x: f32,
    pub y: f32,
    pub z: f32,
    pub w: f32,
}

impl Vector4 {
    #[must_use]
    pub const fn zero() -> Self {
        Self {
            x: 0.0,
            y: 0.0,
            z: 0.0,
            w: 0.0,
        }
    }
    #[must_use]
    pub const fn one() -> Self {
        Self {
            x: 1.0,
            y: 1.0,
            z: 1.0,
            w: 1.0,
        }
    }
    #[must_use]
    pub const fn unit_x() -> Self {
        Self {
            x: 1.0,
            y: 0.0,
            z: 0.0,
            w: 0.0,
        }
    }
    #[must_use]
    pub const fn unit_y() -> Self {
        Self {
            x: 0.0,
            y: 1.0,
            z: 0.0,
            w: 0.0,
        }
    }
    #[must_use]
    pub const fn unit_z() -> Self {
        Self {
            x: 0.0,
            y: 0.0,
            z: 1.0,
            w: 0.0,
        }
    }
    #[must_use]
    pub const fn unit_w() -> Self {
        Self {
            x: 0.0,
            y: 0.0,
            z: 0.0,
            w: 1.0,
        }
    }

    pub const fn new_with_single_single_single_single(
        x: f32,
        y: f32,
        z: f32,
        w: f32,
    ) -> Result<Self, Error> {
        Ok(Self { x, y, z, w })
    }
    pub const fn new_with_vector2_single_single(
        value: Vector2,
        z: f32,
        w: f32,
    ) -> Result<Self, Error> {
        Ok(Self {
            x: value.x,
            y: value.y,
            z,
            w,
        })
    }
    pub const fn new_with_vector3_single(value: Vector3, w: f32) -> Result<Self, Error> {
        Ok(Self {
            x: value.x,
            y: value.y,
            z: value.z,
            w,
        })
    }
    pub const fn new_with_single(value: f32) -> Result<Self, Error> {
        Ok(Self {
            x: value,
            y: value,
            z: value,
            w: value,
        })
    }
    pub const fn new_with_vector4(value: Self) -> Result<Self, Error> {
        Ok(value)
    }
    pub fn new_with_bytes_int32(bytes: Vec<u8>, pos: i32) -> Result<Self, Error> {
        let mut value = Self::zero();
        value.from_bytes(bytes, pos)?;
        Ok(value)
    }
    fn length_squared_value(self) -> f32 {
        self.w * self.w + self.x * self.x + self.y * self.y + self.z * self.z
    }
    fn length_value(self) -> f32 {
        self.length_squared_value().sqrt()
    }
    pub fn length(&mut self) -> Result<f32, Error> {
        Ok(self.length_value())
    }
    pub fn length_squared(&mut self) -> Result<f32, Error> {
        Ok(self.length_squared_value())
    }
    pub fn normalize_with_method(&mut self) -> Result<(), Error> {
        *self = Self::normalize_value(*self);
        Ok(())
    }
    pub fn approx_equals(&mut self, vec: Self, tolerance: f32) -> Result<bool, Error> {
        Ok(Self::distance_squared(*self, vec)? <= tolerance * tolerance)
    }
    pub fn compare_to(&self, vector: Self) -> Result<i32, Error> {
        Ok(compare_f32(self.length_value(), vector.length_value()))
    }
    pub fn is_finite(&self) -> Result<bool, Error> {
        Ok(self.x.is_finite() && self.y.is_finite() && self.z.is_finite() && self.w.is_finite())
    }
    pub fn from_bytes(&mut self, bytes: Vec<u8>, pos: i32) -> Result<(), Error> {
        self.x = read_single_little_endian(&bytes, pos)?;
        self.y =
            read_single_little_endian(&bytes, pos.checked_add(4).ok_or(Error::IndexOutOfRange)?)?;
        self.z =
            read_single_little_endian(&bytes, pos.checked_add(8).ok_or(Error::IndexOutOfRange)?)?;
        self.w =
            read_single_little_endian(&bytes, pos.checked_add(12).ok_or(Error::IndexOutOfRange)?)?;
        Ok(())
    }
    pub fn get_bytes(&self) -> Result<Vec<u8>, Error> {
        let mut bytes = vec![0; 16];
        self.to_bytes(&mut bytes, 0)?;
        Ok(bytes)
    }
    pub fn to_bytes(&self, dest: &mut [u8], pos: i32) -> Result<(), Error> {
        write_single_little_endian(dest, pos, self.x)?;
        write_single_little_endian(
            dest,
            pos.checked_add(4).ok_or(Error::IndexOutOfRange)?,
            self.y,
        )?;
        write_single_little_endian(
            dest,
            pos.checked_add(8).ok_or(Error::IndexOutOfRange)?,
            self.z,
        )?;
        write_single_little_endian(
            dest,
            pos.checked_add(12).ok_or(Error::IndexOutOfRange)?,
            self.w,
        )
    }

    fn add_value(a: Self, b: Self) -> Self {
        Self {
            x: a.x + b.x,
            y: a.y + b.y,
            z: a.z + b.z,
            w: a.w + b.w,
        }
    }
    fn sub_value(a: Self, b: Self) -> Self {
        Self {
            x: a.x - b.x,
            y: a.y - b.y,
            z: a.z - b.z,
            w: a.w - b.w,
        }
    }
    fn mul_value(a: Self, b: Self) -> Self {
        Self {
            x: a.x * b.x,
            y: a.y * b.y,
            z: a.z * b.z,
            w: a.w * b.w,
        }
    }
    fn mul_scalar(a: Self, b: f32) -> Self {
        Self {
            x: a.x * b,
            y: a.y * b,
            z: a.z * b,
            w: a.w * b,
        }
    }
    fn div_value(a: Self, b: Self) -> Self {
        Self {
            x: a.x / b.x,
            y: a.y / b.y,
            z: a.z / b.z,
            w: a.w / b.w,
        }
    }
    fn div_scalar(a: Self, b: f32) -> Self {
        Self::mul_scalar(a, 1.0 / b)
    }
    fn neg_value(a: Self) -> Self {
        Self {
            x: -a.x,
            y: -a.y,
            z: -a.z,
            w: -a.w,
        }
    }
    fn normalize_value(value: Self) -> Self {
        let squared = value.length_squared_value();
        if squared > 0.000_000_1 {
            Self::mul_scalar(value, 1.0 / squared.sqrt())
        } else {
            Self::zero()
        }
    }

    pub fn add_with_vector4_vector4(a: Self, b: Self) -> Result<Self, Error> {
        Ok(Self::add_value(a, b))
    }
    pub fn clamp(value: Self, min: Self, max: Self) -> Result<Self, Error> {
        Ok(Self {
            x: clamp_f32(value.x, min.x, max.x),
            y: clamp_f32(value.y, min.y, max.y),
            z: clamp_f32(value.z, min.z, max.z),
            w: clamp_f32(value.w, min.w, max.w),
        })
    }
    pub fn distance(a: Self, b: Self) -> Result<f32, Error> {
        Ok(Self::distance_squared(a, b)?.sqrt())
    }
    pub fn distance_squared(a: Self, b: Self) -> Result<f32, Error> {
        Ok(Self::sub_value(a, b).length_squared_value())
    }
    pub fn divide_with_vector4_vector4(a: Self, b: Self) -> Result<Self, Error> {
        Ok(Self::div_value(a, b))
    }
    pub fn divide_with_vector4_single(a: Self, b: f32) -> Result<Self, Error> {
        Ok(Self::div_scalar(a, b))
    }
    pub fn dot(a: Self, b: Self) -> Result<f32, Error> {
        Ok(a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w)
    }
    pub fn lerp(a: Self, b: Self, amount: f32) -> Result<Self, Error> {
        Ok(Self {
            x: lerp_f32(a.x, b.x, amount),
            y: lerp_f32(a.y, b.y, amount),
            z: lerp_f32(a.z, b.z, amount),
            w: lerp_f32(a.w, b.w, amount),
        })
    }
    pub fn max(a: Self, b: Self) -> Result<Self, Error> {
        Ok(Self {
            x: max_f32(a.x, b.x),
            y: max_f32(a.y, b.y),
            z: max_f32(a.z, b.z),
            w: max_f32(a.w, b.w),
        })
    }
    pub fn min(a: Self, b: Self) -> Result<Self, Error> {
        Ok(Self {
            x: min_f32(a.x, b.x),
            y: min_f32(a.y, b.y),
            z: min_f32(a.z, b.z),
            w: min_f32(a.w, b.w),
        })
    }
    pub fn multiply_with_vector4_vector4(a: Self, b: Self) -> Result<Self, Error> {
        Ok(Self::mul_value(a, b))
    }
    pub fn multiply_with_vector4_single(a: Self, b: f32) -> Result<Self, Error> {
        Ok(Self::mul_scalar(a, b))
    }
    pub fn negate(value: Self) -> Result<Self, Error> {
        Ok(Self::neg_value(value))
    }
    pub fn normalize_with_vector4(value: Self) -> Result<Self, Error> {
        Ok(Self::normalize_value(value))
    }
    pub fn smooth_step(a: Self, b: Self, amount: f32) -> Result<Self, Error> {
        Ok(Self {
            x: smooth_step_f32(a.x, b.x, amount),
            y: smooth_step_f32(a.y, b.y, amount),
            z: smooth_step_f32(a.z, b.z, amount),
            w: smooth_step_f32(a.w, b.w, amount),
        })
    }
    pub fn subtract(a: Self, b: Self) -> Result<Self, Error> {
        Ok(Self::sub_value(a, b))
    }

    pub fn transform_with_vector2_matrix4(p: Vector2, m: Matrix4) -> Result<Self, Error> {
        Ok(Self {
            x: p.x * m.m11 + p.y * m.m21 + m.m41,
            y: p.x * m.m12 + p.y * m.m22 + m.m42,
            z: p.x * m.m13 + p.y * m.m23 + m.m43,
            w: p.x * m.m14 + p.y * m.m24 + m.m44,
        })
    }
    pub fn transform_with_vector3_matrix4(p: Vector3, m: Matrix4) -> Result<Self, Error> {
        Ok(Self {
            x: p.x * m.m11 + p.y * m.m21 + p.z * m.m31 + m.m41,
            y: p.x * m.m12 + p.y * m.m22 + p.z * m.m32 + m.m42,
            z: p.x * m.m13 + p.y * m.m23 + p.z * m.m33 + m.m43,
            w: p.x * m.m14 + p.y * m.m24 + p.z * m.m34 + m.m44,
        })
    }
    pub fn transform_with_vector4_matrix4(v: Self, m: Matrix4) -> Result<Self, Error> {
        Ok(Self {
            x: v.x * m.m11 + v.y * m.m21 + v.z * m.m31 + v.w * m.m41,
            y: v.x * m.m12 + v.y * m.m22 + v.z * m.m32 + v.w * m.m42,
            z: v.x * m.m13 + v.y * m.m23 + v.z * m.m33 + v.w * m.m43,
            w: v.x * m.m14 + v.y * m.m24 + v.z * m.m34 + v.w * m.m44,
        })
    }
    pub fn parse(val: String) -> Result<Self, Error> {
        let trimmed = val.trim();
        let trimmed = if trimmed.len() >= 2 && trimmed.starts_with('<') && trimmed.ends_with('>') {
            &trimmed[1..trimmed.len() - 1]
        } else {
            trimmed
        };
        let split: Vec<_> = trimmed.split(',').collect();
        if split.len() != 4 {
            return Err(Error::Argument);
        }
        Ok(Self {
            x: parse_f32(split[0])?,
            y: parse_f32(split[1])?,
            z: parse_f32(split[2])?,
            w: parse_f32(split[3])?,
        })
    }
    pub fn try_parse(val: String, result: &mut Self) -> bool {
        match Self::parse(val) {
            Ok(value) => {
                *result = value;
                true
            }
            Err(_) => {
                *result = Self::zero();
                false
            }
        }
    }
    pub fn equals_with_vector4(&self, other: Self) -> bool {
        Self::eq(*self, other)
    }
    pub fn equals_with_object(&self, obj: Option<Object>) -> bool {
        matches!(obj, Some(Object::Vector4(value)) if Self::eq(*self, value))
    }
    pub fn get_hash_code(&self) -> i32 {
        hash_f32(self.x) ^ hash_f32(self.y) ^ hash_f32(self.z) ^ hash_f32(self.w)
    }
    pub fn to_string(&self) -> String {
        format!(
            "<{}, {}, {}, {}>",
            format_f32(self.x),
            format_f32(self.y),
            format_f32(self.z),
            format_f32(self.w)
        )
    }
    pub fn to_raw_string(&self) -> Result<String, Error> {
        Ok(format!(
            "{:.3} {:.3} {:.3} {:.3}",
            self.x, self.y, self.z, self.w
        ))
    }

    pub fn eq(a: Self, b: Self) -> bool {
        a.w == b.w && a.x == b.x && a.y == b.y && a.z == b.z
    }
    pub fn ne(a: Self, b: Self) -> bool {
        !Self::eq(a, b)
    }
    pub fn add_with_vector4_vector4_e5065176(a: Self, b: Self) -> Self {
        Self::add_value(a, b)
    }
    pub fn sub(a: Self, b: Self) -> Self {
        Self::sub_value(a, b)
    }
    pub fn mul_with_vector4_vector4(a: Self, b: Self) -> Self {
        Self::mul_value(a, b)
    }
    pub fn mul_with_vector4_single(a: Self, b: f32) -> Self {
        Self::mul_scalar(a, b)
    }
    pub fn div_with_vector4_vector4(a: Self, b: Self) -> Self {
        Self::div_value(a, b)
    }
    pub fn div_with_vector4_single(a: Self, b: f32) -> Self {
        Self::div_scalar(a, b)
    }
    pub fn neg(value: Self) -> Self {
        Self::neg_value(value)
    }
}

#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct Ray {
    pub origin: Vector3,
    pub direction: Vector3,
}

impl Ray {
    pub const fn new(origin: Vector3, direction: Vector3) -> Result<Self, Error> {
        Ok(Self { origin, direction })
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    fn identity() -> Matrix4 {
        Matrix4 {
            m11: 1.0,
            m12: 0.0,
            m13: 0.0,
            m14: 0.0,
            m21: 0.0,
            m22: 1.0,
            m23: 0.0,
            m24: 0.0,
            m31: 0.0,
            m32: 0.0,
            m33: 1.0,
            m34: 0.0,
            m41: 0.0,
            m42: 0.0,
            m43: 0.0,
            m44: 1.0,
        }
    }

    #[test]
    fn vector_binary_round_trips_preserve_bits_and_offsets() {
        let vector2 = Vector2 {
            x: -0.0,
            y: f32::from_bits(0x7fc0_1234),
        };
        let mut bytes = [0xaa; 19];
        vector2.to_bytes(&mut bytes, 3).unwrap();
        let mut decoded2 = Vector2::zero();
        decoded2.from_bytes(bytes.to_vec(), 3).unwrap();
        assert_eq!(decoded2.x.to_bits(), vector2.x.to_bits());
        assert_eq!(decoded2.y.to_bits(), vector2.y.to_bits());
        assert_eq!(&bytes[..3], &[0xaa; 3]);
        assert_eq!(&bytes[11..], &[0xaa; 8]);

        let vector3 = Vector3 {
            x: 1.25,
            y: -2.5,
            z: f32::INFINITY,
        };
        let decoded3 = Vector3::from_bytes(vector3.get_bytes().unwrap(), 0).unwrap();
        assert_eq!(decoded3.x.to_bits(), vector3.x.to_bits());
        assert_eq!(decoded3.y.to_bits(), vector3.y.to_bits());
        assert_eq!(decoded3.z.to_bits(), vector3.z.to_bits());

        let vector3d = Vector3d {
            x: f64::MIN_POSITIVE,
            y: -12.5,
            z: f64::from_bits(1),
        };
        let decoded3d = Vector3d::new_with_bytes_int32(vector3d.get_bytes().unwrap(), 0).unwrap();
        assert_eq!(decoded3d.x.to_bits(), vector3d.x.to_bits());
        assert_eq!(decoded3d.y.to_bits(), vector3d.y.to_bits());
        assert_eq!(decoded3d.z.to_bits(), vector3d.z.to_bits());

        let vector4 = Vector4 {
            x: 1.0,
            y: 2.0,
            z: 3.0,
            w: 4.0,
        };
        assert_eq!(
            Vector4::new_with_bytes_int32(vector4.get_bytes().unwrap(), 0).unwrap(),
            vector4
        );
    }

    #[test]
    fn vector_output_buffers_fail_at_the_reference_boundary() {
        let mut short = [0xaa; 5];
        assert_eq!(
            Vector2::one().to_bytes(&mut short, 0),
            Err(Error::IndexOutOfRange)
        );
        assert_eq!(&short[..4], &1.0_f32.to_le_bytes());
        assert_eq!(short[4], 0xaa);
        assert_eq!(
            Vector3::one().to_bytes(&mut [0; 12], -1),
            Err(Error::IndexOutOfRange)
        );
    }

    #[test]
    fn arithmetic_properties_hold_for_representative_finite_values() {
        for [x, y, z] in [[1.0, 2.0, 3.0], [-4.5, 0.25, 8.0], [0.0001, -0.002, 17.0]] {
            let value = Vector3 { x, y, z };
            let scale = 2.5;
            let restored = Vector3::div_with_vector3_single(
                Vector3::mul_with_vector3_single(value, scale),
                scale,
            );
            assert!(Vector3::eq(value, restored));
            let normalized = Vector3::normalize(value).unwrap();
            assert!((normalized.length_value() - 1.0).abs() <= 2.0 * f32::EPSILON);
            assert!(
                (Vector3::dot(value, Vector3::cross_value(value, Vector3::unit_x())).unwrap())
                    .abs()
                    <= 0.000_01
            );
        }
    }

    #[test]
    fn normalization_thresholds_and_zero_behavior_match_reference() {
        assert_eq!(
            Vector2::normalize_with_vector2(Vector2 { x: 0.0001, y: 0.0 }).unwrap(),
            Vector2::zero()
        );
        assert_eq!(
            Vector4::normalize_with_vector4(Vector4 {
                x: 0.0001,
                y: 0.0,
                z: 0.0,
                w: 0.0
            })
            .unwrap(),
            Vector4::zero()
        );
        assert_eq!(
            Vector3::normalize(Vector3 {
                x: 0.000_000_1,
                y: 0.0,
                z: 0.0
            })
            .unwrap(),
            Vector3::zero()
        );
        assert_eq!(
            Vector3d::normalize_with_vector3d(Vector3d {
                x: f64::from_bits(1),
                y: 0.0,
                z: 0.0
            })
            .unwrap(),
            Vector3d::zero()
        );
        assert_eq!(Vector3d::one(), Vector3d::zero());
    }

    #[test]
    fn parsing_formatting_and_failed_try_parse_match_reference() {
        let value = Vector2::parse("  <1.25, -2.5>  ".to_owned()).unwrap();
        assert_eq!(value, Vector2 { x: 1.25, y: -2.5 });
        assert_eq!(value.to_string(), "<1.25, -2.5>");
        assert_eq!(value.to_raw_string().unwrap(), "1.250 -2.500");
        let mut output = Vector4::one();
        assert!(!Vector4::try_parse("<1, 2, 3>".to_owned(), &mut output));
        assert_eq!(output, Vector4::zero());
        assert_eq!(
            Vector3d::parse("<<1>, 2, 3, 999>".to_owned()).unwrap(),
            Vector3d {
                x: 1.0,
                y: 2.0,
                z: 3.0
            }
        );
    }

    #[test]
    fn transforms_and_quaternion_rotation_use_reference_equations() {
        let value = Vector3 {
            x: 1.0,
            y: -2.0,
            z: 3.0,
        };
        assert_eq!(Vector3::transform(value, identity()).unwrap(), value);
        assert_eq!(
            Vector4::transform_with_vector3_matrix4(value, identity()).unwrap(),
            Vector4 {
                x: 1.0,
                y: -2.0,
                z: 3.0,
                w: 1.0
            }
        );
        let quarter_turn = Quaternion {
            x: 0.0,
            y: 0.0,
            z: std::f32::consts::FRAC_1_SQRT_2,
            w: std::f32::consts::FRAC_1_SQRT_2,
        };
        let rotated = Vector3::mul_with_vector3_quaternion(Vector3::unit_x(), quarter_turn);
        assert!(rotated.x.abs() <= f32::EPSILON);
        assert!((rotated.y - 1.0).abs() <= f32::EPSILON);

        let matrix = Matrix4 {
            m11: 2.0,
            m12: 3.0,
            m21: 5.0,
            m22: 7.0,
            ..identity()
        };
        // Vector2.Transform in the golden source intentionally uses the updated X for Y.
        assert_eq!(
            Vector2::transform(Vector2 { x: 11.0, y: 13.0 }, matrix).unwrap(),
            Vector2 { x: 87.0, y: 352.0 }
        );
    }

    #[test]
    fn equality_hash_and_ray_storage_are_compatible() {
        let plus_zero = Vector3 {
            x: 0.0,
            y: 1.0,
            z: 2.0,
        };
        let minus_zero = Vector3 {
            x: -0.0,
            y: 1.0,
            z: 2.0,
        };
        assert!(plus_zero.equals_with_vector3(minus_zero));
        assert_eq!(plus_zero.get_hash_code(), minus_zero.get_hash_code());
        assert!(plus_zero.equals_with_object(Some(Object::from(plus_zero))));
        let ray = Ray::new(plus_zero, Vector3::unit_z()).unwrap();
        assert_eq!(ray.origin, plus_zero);
        assert_eq!(ray.direction, Vector3::unit_z());
    }
}
