context: #region License
  // Copyright (c) 2013 Antonie Blom
  // 
  // Permission is hereby granted, free of charge, to any person obtaining a copy
  // of this software and associated documentation files (the "Software"), to deal
  // in the Software without restriction, including without limitation the rights to
  // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  // the Software, and to permit persons to whom the Software is furnished to do
  // so, subject to the following conditions:
  // 
  // The above copyright notice and this permission notice shall be included in all
  // copies or substantial portions of the Software.
  // 
  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  // OTHER DEALINGS IN THE SOFTWARE.
  #endregion
  
  using System;
  using System.Runtime.InteropServices;
  using System.Xml.Serialization;
  
  namespace FreezingArcher.Math {
  	/// <summary>
  	/// Represents a 3D vector using three single-precision floating-point numbers.
  	/// </summary>
  	/// <remarks>
  	/// The Vector3i structure is suitable for interoperation with unmanaged code requiring three consecutive floats.
  	/// </remarks>
  	[Serializable]
  	[StructLayout(LayoutKind.Sequential)]
  	public struct Vector3i : IEquatable<Vector3i> {
  		/// <summary>
  		/// The X component of the Vector3i.
  		/// </summary>
  		public int X;
  
  		/// <summary>
  		/// The Y component of the Vector3i.
  		/// </summary>
  		public int Y;
  
  		/// <summary>
  		/// The Z component of the Vector3i.
  		/// </summary>
  		public int Z;
  
  		/// <summary>
  		/// Defines a unit-length Vector3i that points towards the X-axis.
  		/// </summary>
  		public static readonly Vector3i UnitX = new Vector3i(1, 0, 0);
  
  		/// <summary>
  		/// Defines a unit-length Vector3i that points towards the Y-axis.
  		/// </summary>
  		public static readonly Vector3i UnitY = new Vector3i(0, 1, 0);
  
  		/// <summary>
  		/// /// Defines a unit-length Vector3i that points towards the Z-axis.
  		/// </summary>
  		public static readonly Vector3i UnitZ = new Vector3i(0, 0, 1);
  
  		/// <summary>
  		/// Defines a zero-length Vector3i.
  		/// </summary>
  		public static readonly Vector3i Zero = new Vector3i(0, 0, 0);
  
  		/// <summary>
  		/// Defines an instance with all components set to 1.
  		/// </summary>
  		public static readonly Vector3i One = new Vector3i(1, 1, 1);
  
  		/// <summary>
  		/// Defines the size of the Vector3i struct in bytes.
  		/// </summary>
  		public const int SizeInBytes = sizeof(int) * 3;
  
  		/// <summary>
  		/// Constructs a new instance.
  		/// </summary>
  		/// <param name="value">The value that will initialize this instance.</param>
  		public Vector3i(int value) {
  			X = value;
  			Y = value;
  			Z = value;
  		}
  
  		/// <summary>
  		/// Constructs a new Vector3i.
  		/// </summary>
  		/// <param name="x">The x component of the Vector3i.</param>
  		/// <param name="y">The y component of the Vector3i.</param>
  		/// <param name="z">The z component of the Vector3i.</param>
  		public Vector3i(int x, int y, int z) {
  			X = x;
  			Y = y;
  			Z = z;
  		}
  
  		/// <summary>
  		/// Constructs a new Vector3i from the given Vector2.
  		/// </summary>
  		/// <param name="v">The Vector2 to copy components from.</param>
  		public Vector3i(Vector2i v) {
  			X = v.X;
  			Y = v.Y;
  			Z = 0;
  		}
  
  		/// <summary>
  		/// Constructs a new Vector3i from the given Vector3i.
  		/// </summary>
  		/// <param name="v">The Vector3i to copy components from.</param>
  		public Vector3i(Vector3i v) {
  			X = v.X;
  			Y = v.Y;
  			Z = v.Z;
  		}
  
  		/// <summary>
  		/// Constructs a new Vector3i from the given Vector4.
  		/// </summary>
  		/// <param name="v">The Vector4 to copy components from.</param>
  		public Vector3i(Vector4i v) {
  			X = v.X;
  			Y = v.Y;
  			Z = v.Z;
  		}
  
  
  		/// <summary>
  		/// Gets or sets the value at the index of the Vector.
  		/// </summary>
  		public int this[int index] {
  			get {
  				if (index == 0)
  					return X;
  				else if (index == 1)
  					return Y;
  				else if (index == 2)
  					return Z;
  				throw new IndexOutOfRangeException("You tried to access this vector at index: " + index);
  			} set {
  				if (index == 0)
  					X = value;
  				else if (index == 1)
  					Y = value;
  				else if (index == 2)
  					Z = value;
  				throw new IndexOutOfRangeException("You tried to set this vector at index: " + index);
  			}
  		}
  
  		/// <summary>
  		/// Gets the length (magnitude) of the vector.
  		/// </summary>
  		/// <see cref="LengthFast"/>
  		/// <seealso cref="LengthSquared"/>
  		public float Length {
  			get { return (float)System.Math.Sqrt(X * X + Y * Y + Z * Z); }
  		}
  
  		/// <summary>
  		/// Gets an approximation of the vector length (magnitude).
  		/// </summary>
  		/// <remarks>
  		/// This property uses an approximation of the square root function to calculate vector magnitude, with
  		/// an upper error bound of 0.001.
  		/// </remarks>
  		/// <see cref="Length"/>
  		/// <seealso cref="LengthSquared"/>
  		public float LengthFast {
  			get { return 1.0f / MathHelper.InverseSqrtFast(X * X + Y * Y + Z * Z); }
  		}
  
  		/// <summary>
  		/// Gets the square of the vector length (magnitude).
  		/// </summary>
  		/// <remarks>
  		/// This property avoids the costly square root operation required by the Length property. This makes it more suitable
  		/// for comparisons.
  		/// </remarks>
  		/// <see cref="Length"/>
  		/// <seealso cref="LengthFast"/>
  		public int LengthSquared {
  			get { return X * X + Y * Y + Z * Z; }
  		}
  
  		/// <summary>
  		/// Adds two vectors.
  		/// </summary>
  		/// <param name="a">Left operand.</param>
  		/// <param name="b">Right operand.</param>
  		/// <returns>Result of operation.</returns>
  		public static Vector3i Add(Vector3i a, Vector3i b) {
  			Add(ref a, ref b, out a);
  			return a;
  		}
  
  		/// <summary>
  		/// Adds two vectors.
  		/// </summary>
  		/// <param name="a">Left operand.</param>
  		/// <param name="b">Right operand.</param>
  		/// <param name="result">Result of operation.</param>
  		public static void Add(ref Vector3i a, ref Vector3i b, out Vector3i result) {
  			result = new Vector3i(a.X + b.X, a.Y + b.Y, a.Z + b.Z);
  		}
  
  		/// <summary>
  		/// Subtract one Vector from another
  		/// </summary>
  		/// <param name="a">First operand</param>
  		/// <param name="b">Second operand</param>
  		/// <returns>Result of subtraction</returns>
  		public static Vector3i Subtract(Vector3i a, Vector3i b) {
  			Subtract(ref a, ref b, out a);
  			return a;
  		}
  
  		/// <summary>
  		/// Subtract one Vector from another
  		/// </summary>
  		/// <param name="a">First operand</param>
  		/// <param name="b">Second operand</param>
  		/// <param name="result">Result of subtraction</param>
  		public static void Subtract(ref Vector3i a, ref Vector3i b, out Vector3i result) {
  			result = new Vector3i(a.X - b.X, a.Y - b.Y, a.Z - b.Z);
  		}
  
  		/// <summary>
  		/// Multiplies a vector by a scalar.
  		/// </summary>
  		/// <param name="vector">Left operand.</param>
  		/// <param name="scale">Right operand.</param>
  		/// <returns>Result of the operation.</returns>
  		public static Vector3i Multiply(Vector3i vector, int scale) {
  			Multiply(ref vector, scale, out vector);
  			return vector;
  		}
  
  		/// <summary>
  		/// Multiplies a vector by a scalar.
  		/// </summary>
  		/// <param name="vector">Left operand.</param>
  		/// <param name="scale">Right operand.</param>
  		/// <param name="result">Result of the operation.</param>
  		public static void Multiply(ref Vector3i vector, int scale, out Vector3i result) {
  			result = new Vector3i(vector.X * scale, vector.Y * scale, vector.Z * scale);
  		}
  
  		/// <summary>
  		/// Multiplies a vector by the components a vector (scale).
  		/// </summary>
  		/// <param name="vector">Left operand.</param>
  		/// <param name="scale">Right operand.</param>
  		/// <returns>Result of the operation.</returns>
  		public static Vector3i Multiply(Vector3i vector, Vector3i scale) {
  			Multiply(ref vector, ref scale, out vector);
  			return vector;
  		}
  
  		/// <summary>
  		/// Multiplies a vector by the components of a vector (scale).
  		/// </summary>
  		/// <param name="vector">Left operand.</param>
  		/// <param name="scale">Right operand.</param>
  		/// <param name="result">Result of the operation.</param>
  		public static void Multiply(ref Vector3i vector, ref Vector3i scale, out Vector3i result) {
  			result = new Vector3i(vector.X * scale.X, vector.Y * scale.Y, vector.Z * scale.Z);
  		}
  
  		/// <summary>
  		/// Divides a vector by a scalar.
  		/// </summary>
  		/// <param name="vector">Left operand.</param>
  		/// <param name="scale">Right operand.</param>
  		/// <returns>Result of the operation.</returns>
  		public static Vector3i Divide(Vector3i vector, int scale) {
  			Divide(ref vector, scale, out vector);
  			return vector;
  		}
  
  		/// <summary>
  		/// Divides a vector by a scalar.
  		/// </summary>
  		/// <param name="vector">Left operand.</param>
  		/// <param name="scale">Right operand.</param>
  		/// <param name="result">Result of the operation.</param>
  		public static void Divide(ref Vector3i vector, int scale, out Vector3i result) {
  			Multiply(ref vector, 1 / scale, out result);
  		}
  
  		/// <summary>
  		/// Divides a vector by the components of a vector (scale).
  		/// </summary>
  		/// <param name="vector">Left operand.</param>
  		/// <param name="scale">Right operand.</param>
  		/// <returns>Result of the operation.</returns>
  		public static Vector3i Divide(Vector3i vector, Vector3i scale) {
  			Divide(ref vector, ref scale, out vector);
  			return vector;
  		}
  
  		/// <summary>
  		/// Divide a vector by the components of a vector (scale).
  		/// </summary>
  		/// <param name="vector">Left operand.</param>
  		/// <param name="scale">Right operand.</param>
  		/// <param name="result">Result of the operation.</param>
  		public static void Divide(ref Vector3i vector, ref Vector3i scale, out Vector3i result) {
  			result = new Vector3i(vector.X / scale.X, vector.Y / scale.Y, vector.Z / scale.Z);
  		}
  
  		/// <summary>
  		/// Calculate the component-wise minimum of two vectors
  		/// </summary>
  		/// <param name="a">First operand</param>
  		/// <param name="b">Second operand</param>
  		/// <returns>The component-wise minimum</returns>
  		public static Vector3i ComponentMin(Vector3i a, Vector3i b) {
  			a.X = a.X < b.X ? a.X : b.X;
  			a.Y = a.Y < b.Y ? a.Y : b.Y;
  			a.Z = a.Z < b.Z ? a.Z : b.Z;
  			return a;
  		}
  
  		/// <summary>
  		/// Calculate the component-wise minimum of two vectors
  		/// </summary>
  		/// <param name="a">First operand</param>
  		/// <param name="b">Second operand</param>
  		/// <param name="result">The component-wise minimum</param>
  		public static void ComponentMin(ref Vector3i a, ref Vector3i b, out Vector3i result) {
  			result.X = a.X < b.X ? a.X : b.X;
  			result.Y = a.Y < b.Y ? a.Y : b.Y;
  			result.Z = a.Z < b.Z ? a.Z : b.Z;
  		}
  
  		/// <summary>
  		/// Calculate the component-wise maximum of two vectors
  		/// </summary>
  		/// <param name="a">First operand</param>
  		/// <param name="b">Second operand</param>
  		/// <returns>The component-wise maximum</returns>
  		public static Vector3i ComponentMax(Vector3i a, Vector3i b) {
  			a.X = a.X > b.X ? a.X : b.X;
  			a.Y = a.Y > b.Y ? a.Y : b.Y;
  			a.Z = a.Z > b.Z ? a.Z : b.Z;
  			return a;
  		}
  
  		/// <summary>
  		/// Calculate the component-wise maximum of two vectors
  		/// </summary>
  		/// <param name="a">First operand</param>
  		/// <param name="b">Second operand</param>
  		/// <param name="result">The component-wise maximum</param>
  		public static void ComponentMax(ref Vector3i a, ref Vector3i b, out Vector3i result) {
  			result.X = a.X > b.X ? a.X : b.X;
  			result.Y = a.Y > b.Y ? a.Y : b.Y;
  			result.Z = a.Z > b.Z ? a.Z : b.Z;
  		}
  
  		/// <summary>
  		/// Returns the Vector3i with the minimum magnitude
  		/// </summary>
  		/// <param name="left">Left operand</param>
  		/// <param name="right">Right operand</param>
  		/// <returns>The minimum Vector3i</returns>
  		public static Vector3i Min(Vector3i left, Vector3i right) {
  			return left.LengthSquared < right.LengthSquared ? left : right;
  		}
  
  		/// <summary>
  		/// Returns the Vector3i with the minimum magnitude
  		/// </summary>
  		/// <param name="left">Left operand</param>
  		/// <param name="right">Right operand</param>
  		/// <returns>The minimum Vector3i</returns>
  		public static Vector3i Max(Vector3i left, Vector3i right) {
  			return left.LengthSquared >= right.LengthSquared ? left : right;
  		}
  
  		/// <summary>
  		/// Clamp a vector to the given minimum and maximum vectors
  		/// </summary>
  		/// <param name="vec">Input vector</param>
  		/// <param name="min">Minimum vector</param>
  		/// <param name="max">Maximum vector</param>
  		/// <returns>The clamped vector</returns>
  		public static Vector3i Clamp(Vector3i vec, Vector3i min, Vector3i max) {
  
gt: 			vec.X = vec.X < min.X ? min.X : vec.X > max.X ? max.X : vec.X;