using System;

namespace InterpreterLibrary.Models
{
    public struct Vector3
    {
        
        
        
        public float X;

        
        
        
        public float Y;

        
        
        
        public float Z;

        
        
        
        
        
        
        
        public Vector3(float value)
        {
            X = Y = Z = value;
        }

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

        
        
        
        
        
        
        
        
        
        public int MinIndex => Array.IndexOf(new[] {X, Y, Z}, Min);

        
        
        
        
        
        
        
        
        
        public int MinMaxIndex => Array.IndexOf(new[] {X, Y, Z}, Max);

        
        
        
        
        
        
        public float Min => Math.Min(Math.Min(X, Y), Z);

        
        
        
        
        
        
        public float Max => Math.Max(Math.Max(X, Y), Z);

        
        
        
        
        
        
        public float Norm => (float) Math.Sqrt(Square);

        
        
        
        
        
        
        
        public float Square => (float) (Math.Pow(X, 2) + Math.Pow(Y, 2) + Math.Pow(Z, 2));

        
        
        
        
        
        
        
        
        
        
        
        
        
        
        public static Vector3 Add(Vector3 vector1, Vector3 vector2)
        {
            return new Vector3(vector1.X + vector2.X, vector1.Y + vector2.Y, vector1.Z + vector2.Z);
        }

        
        
        
        
        
        
        
        
        
        
        
        
        
        public static Vector3 Add(Vector3 vector, float value)
        {
            return new Vector3(vector.X + value, vector.Y + value, vector.Z + value);
        }

        
        
        
        
        
        
        
        
        
        
        
        
        
        public static Vector3 Cross(Vector3 vector1, Vector3 vector2)
        {
            return new Vector3(
                vector1.Y * vector2.Z - vector1.Z * vector2.Y,
                vector1.Z * vector2.X - vector1.X * vector2.Z,
                vector1.X * vector2.Y - vector1.Y * vector2.X);
        }

        
        
        
        
        
        
        
        
        
        
        
        
        
        public static Vector3 Divide(Vector3 vector, float factor)
        {
            return vector / factor;
        }

        
        
        
        
        
        
        
        
        
        
        
        
        
        
        public static Vector3 Divide(Vector3 vector1, Vector3 vector2)
        {
            return vector1 / vector2;
        }

        
        
        
        
        
        
        
        
        
        
        
        
        
        public static float Dot(Vector3 vector1, Vector3 vector2)
        {
            return vector1.X * vector2.X +
                   vector1.Y * vector2.Y +
                   vector1.Z * vector2.Z;
        }

        
        
        
        
        
        
        
        
        
        
        
        
        
        
        public static Vector3 Multiply(Vector3 vector1, Vector3 vector2)
        {
            return vector1 * vector2;
        }

        
        
        
        
        
        
        
        
        
        
        
        
        
        public static Vector3 Multiply(Vector3 vector, float factor)
        {
            return vector * factor;
        }

        
        
        
        
        
        
        
        
        
        
        
        
        
        
        public static Vector3 Subtract(Vector3 vector1, Vector3 vector2)
        {
            return vector1 - vector2;
        }

        
        
        
        
        
        
        
        
        
        
        
        
        
        public static Vector3 Subtract(Vector3 vector, float value)
        {
            return vector - value;
        }

        
        
        
        
        
        
        
        public Vector3 Abs()
        {
            return new Vector3(Math.Abs(X), Math.Abs(Y), Math.Abs(Z));
        }

        
        
        
        
        
        
        
        
        
        
        public override bool Equals(object obj)
        {
            return base.Equals(obj);
        }

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

        
        
        
        
        
        
        public override int GetHashCode()
        {
            return (int) X ^ (int) Y ^ (int) Z;
        }

        
        
        
        
        
        
        
        
        public Vector3 Inverse()
        {
            var x = X == 0.0f ? 0.0f : 1 / X;
            var y = Y == 0.0f ? 0.0f : 1 / Y;
            var z = Z == 0.0f ? 0.0f : 1 / Z;
            return new Vector3(x, y, z);
        }

        
        
        
        
        
        
        public float Normalize()
        {
            var norm = Norm;
            X /= norm;
            Y /= norm;
            Z /= norm;
            return norm;
        }

        
        
        
        
        
        
        public float[] ToArray()
        {
            return new[] {X, Y, Z};
        }

        
        
        
        
        
        
        public override string ToString()
        {
            return $"[{X} {Y} {Z}]";
        }
        
        
        
        
        
        
        
        
        
        
        

        
        
        
        
        
        
        
        
        
        
        
        
        
        
        public static Vector3 operator +(Vector3 vector1, Vector3 vector2)
        {
            return Add(vector1, vector2);
        }

        
        
        
        
        
        
        
        
        
        
        
        
        
        public static Vector3 operator +(Vector3 vector, float value)
        {
            return Add(vector, value);
        }

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

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

        
        
        
        
        
        
        
        
        
        
        
        
        
        public static Vector3 operator *(Vector3 vector, float factor)
        {
            return new Vector3(vector.X * factor, vector.Y * factor, vector.Y * factor);
        }

        
        
        
        
        
        
        
        
        
        
        
        
        
        
        public static Vector3 operator *(Vector3 vector1, Vector3 vector2)
        {
            return new Vector3(vector1.X * vector2.X, vector1.Y * vector2.Y, vector1.Z * vector2.Z);
        }

        
        
        
        
        
        
        
        
        
        
        
        
        
        public static Vector3 operator /(Vector3 vector, float factor)
        {
            return new Vector3(vector.X / factor, vector.Y / factor, vector.Y / factor);
        }

        
        
        
        
        
        
        
        
        
        
        
        
        
        
        public static Vector3 operator /(Vector3 vector1, Vector3 vector2)
        {
            return new Vector3(vector1.X / vector2.X, vector1.Y / vector2.Y, vector1.Z / vector2.Z);
        }

        
        
        
        
        
        
        
        
        
        
        
        
        
        public static bool operator ==(Vector3 vector1, Vector3 vector2)
        {
            return vector1.Equals(vector2);
        }

        
        
        
        
        
        
        
        
        
        
        
        
        
        public static bool operator !=(Vector3 vector1, Vector3 vector2)
        {
            return !vector1.Equals(vector2);
        }
    }
}
