from math import sqrt


class Vector3:
    X: float
    Y: float
    Z: float

    def __init__(self, *args):
        if len(args) == 3 or len(args) == 1 and isinstance(args[0], (tuple, list)):
            self.X, self.Y, self.Z = args
        elif len(args) == 1:
            # dirty patch for Vector4
            self.__dict__ = args[0].__dict__

    def length(self) -> float:
        return sqrt(self.X ** 2 + self.Y ** 2 + self.Z ** 2)

    def normalize(self):
        length = self.length()

        invNorm = 1.0 / length
        self.X *= invNorm
        self.Y *= invNorm
        self.Z *= invNorm


"""
using System;
using System.Runtime.InteropServices;

namespace AssetStudio
{
	[StructLayout(LayoutKind.Sequential, Pack = 4)]
	public struct Vector3 : IEquatable<Vector3>
	{
		public float X;
		public float Y;
		public float Z;

		public Vector3(float x, float y, float z)
		{
			X = x;
			Y = y;
			Z = z;
		}

		public float this[int index]
		{
			get
			{
				switch (index)
				{
					case 0: return X;
					case 1: return Y;
					case 2: return Z;
					default: throw new ArgumentOutOfRangeException(nameof(index), "Invalid Vector3 index!");
				}
			}

			set
			{
				switch (index)
				{
					case 0: X = value; break;
					case 1: Y = value; break;
					case 2: Z = value; break;
					default: throw new ArgumentOutOfRangeException(nameof(index), "Invalid Vector3 index!");
				}
			}
		}

		public override int GetHashCode()
		{
			return X.GetHashCode() ^ (Y.GetHashCode() << 2) ^ (Z.GetHashCode() >> 2);
		}

		public override bool Equals(object other)
		{
			if (!(other is Vector3))
				return false;
			return Equals((Vector3)other);
		}

		public bool Equals(Vector3 other)
		{
			return X.Equals(other.X) && Y.Equals(other.Y) && Z.Equals(other.Z);
		}

		public void Normalize()
		{
			var length = Length();
			if (length > kEpsilon)
			{
				var invNorm = 1.0f / length;
				X *= invNorm;
				Y *= invNorm;
				Z *= invNorm;
			}
			else
			{
				X = 0;
				Y = 0;
				Z = 0;
			}
		}

		public float Length()
		{
			return (float)Math.Sqrt(LengthSquared());
		}

		public float LengthSquared()
		{
			return X * X + Y * Y + Z * Z;
		}

		public static Vector3 Zero => new Vector3();

		public static Vector3 operator +(Vector3 a, Vector3 b)
		{
			return new Vector3(a.X + b.X, a.Y + b.Y, a.Z + b.Z);
		}

		public static Vector3 operator -(Vector3 a, Vector3 b)
		{
			return new Vector3(a.X - b.X, a.Y - b.Y, a.Z - b.Z);
		}

		public static Vector3 operator -(Vector3 a)
		{
			return new Vector3(-a.X, -a.Y, -a.Z);
		}

		public static Vector3 operator *(Vector3 a, float d)
		{
			return new Vector3(a.X * d, a.Y * d, a.Z * d);
		}

		public static Vector3 operator *(float d, Vector3 a)
		{
			return new Vector3(a.X * d, a.Y * d, a.Z * d);
		}

		public static Vector3 operator /(Vector3 a, float d)
		{
			return new Vector3(a.X / d, a.Y / d, a.Z / d);
		}

		public static bool operator ==(Vector3 lhs, Vector3 rhs)
		{
			return (lhs - rhs).LengthSquared() < kEpsilon * kEpsilon;
		}

		public static bool operator !=(Vector3 lhs, Vector3 rhs)
		{
			return !(lhs == rhs);
		}

		public static implicit operator Vector2(Vector3 v)
		{
			return new Vector2(v.X, v.Y);
		}

		public static implicit operator Vector4(Vector3 v)
		{
			return new Vector4(v.X, v.Y, v.Z, 0.0F);
		}

		private const float kEpsilon = 0.00001F;
	}
}

"""
