Context:
#region MIT License
/*
 * Copyright (c) 2005-2007 Jonathan Mark Porter. http://physics2d.googlepages.com/
 *
 * 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

#if UseDouble
using Scalar = System.Double;
#else
using Scalar = System.Single;
#endif
using System;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Xml.Serialization;
using AdvanceMath.Design;
namespace AdvanceMath
{
    /// <summary>
    /// (NOT USED BY PHYSICS2D)
    /// </summary>
    /// <remarks><seealso href="http://en.wikipedia.org/wiki/Vector_%28spatial%29"/></remarks>
    //[StructLayout(LayoutKind.Sequential), Serializable]
    [StructLayout(LayoutKind.Sequential, Size = Vector4D.Size, Pack = 0), Serializable]
    [AdvBrowsableOrder("X,Y,Z,W")]
    [System.ComponentModel.TypeConverter(typeof(AdvTypeConverter<Vector4D>))]
    public struct Vector4D : IVector<Vector4D>
    {
        #region const fields
        /// <summary>
        /// The number of Scalar values in the class.
        /// </summary>
        public const int Count = 4;
        /// <summary>
        /// The Size of the class in bytes;
        /// </summary>
        public const int Size = sizeof(Scalar) * Count;
        #endregion
        #region readonly fields
        /// <summary>
        /// Vector4D(0,0,0,0)
        /// </summary>
        public static readonly Vector4D Origin = new Vector4D();
        /// <summary>
        /// Vector4D(0,0,0,0)
        /// </summary>
        public static readonly Vector4D Zero = new Vector4D();
        /// <summary>
        /// Vector4D(1,0,0,0)
        /// </summary>
        public static readonly Vector4D XAxis = new Vector4D(1, 0, 0, 0);
        /// <summary>
        /// Vector4D(0,1,0,0)
        /// </summary>
        public static readonly Vector4D YAxis = new Vector4D(0, 1, 0, 0);
        /// <summary>
        /// Vector4D(0,0,1,0)
        /// </summary>
        public static readonly Vector4D ZAxis = new Vector4D(0, 0, 1, 0);
        /// <summary>
        /// Vector4D(0,0,0,1)
        /// </summary>
        public static readonly Vector4D WAxis = new Vector4D(0, 0, 0, 1);

        private static readonly string FormatString = MatrixHelper.CreateVectorFormatString(Count);
        private readonly static string FormatableString = MatrixHelper.CreateVectorFormatableString(Count);

        #endregion
        #region static methods
        public static void Copy(ref Vector4D vector, Scalar[] destArray)
        {
            Copy(ref vector, destArray, 0);
        }
        public static void Copy(ref Vector4D vector, Scalar[] destArray, int index)
        {
            ThrowHelper.CheckCopy(destArray, index, Count);

            destArray[index] = vector.X;
            destArray[++index] = vector.Y;
            destArray[++index] = vector.Z;
            destArray[++index] = vector.W;
        }
        public static void Copy(Scalar[] sourceArray, out Vector4D result)
        {
            Copy(sourceArray, 0, out result);
        }
        public static void Copy(Scalar[] sourceArray, int index, out Vector4D result)
        {
            ThrowHelper.CheckCopy(sourceArray, index, Count);

            result.X = sourceArray[index];
            result.Y = sourceArray[++index];
            result.Z = sourceArray[++index];
            result.W = sourceArray[++index];
        }
        public static void Copy(ref Vector3D source, ref Vector4D dest)
        {
            dest.X = source.X;
            dest.Y = source.Y;
            dest.Z = source.Z;
        }
        public static void Copy(ref Vector2D source, ref Vector4D dest)
        {
            dest.X = source.X;
            dest.Y = source.Y;
        }

        public static Vector4D Clamp(Vector4D value, Vector4D lower, Vector4D upper)
        {
            Vector4D result;
            MathHelper.Clamp(ref value.X, ref  lower.X, ref  upper.X, out result.X);
            MathHelper.Clamp(ref value.Y, ref  lower.Y, ref  upper.Y, out result.Y);
            MathHelper.Clamp(ref value.Z, ref  lower.Z, ref  upper.Z, out result.Z);
            MathHelper.Clamp(ref value.W, ref  lower.W, ref  upper.W, out result.W);
            return result;
        }
        public static void Clamp(ref Vector4D value, ref Vector4D lower, ref Vector4D upper, out Vector4D result)
        {
            MathHelper.Clamp(ref value.X, ref  lower.X, ref  upper.X, out result.X);
            MathHelper.Clamp(ref value.Y, ref  lower.Y, ref  upper.Y, out result.Y);
            MathHelper.Clamp(ref value.Z, ref  lower.Z, ref  upper.Z, out result.Z);
            MathHelper.Clamp(ref value.W, ref  lower.W, ref  upper.W, out result.W);
        }

        public static Vector4D Lerp( Vector4D left,  Vector4D right,  Scalar amount)
        {
            Vector4D result;
            Lerp(ref left,ref right,ref amount,out result);
            return result;
        }
        public static void Lerp(ref Vector4D left, ref Vector4D right, ref Scalar amount, out Vector4D result)
        {
            result.X = (right.X - left.X) * amount + left.X;
            result.Y = (right.Y - left.Y) * amount + left.Y;
            result.Z = (right.Z - left.Z) * amount + left.Z;
            result.W = (right.W - left.W) * amount + left.W;
        }
        public static Vector4D Lerp(Vector4D left, Vector4D right, Vector4D amount)
        {
            Vector4D result;
            Lerp(ref left, ref right, ref amount, out result);
            return result;
        }
        public static void Lerp(ref Vector4D left, ref Vector4D right, ref Vector4D amount, out Vector4D result)
        {
            result.X = (right.X - left.X) * amount.X + left.X;
            result.Y = (right.Y - left.Y) * amount.Y + left.Y;
            result.Z = (right.Z - left.Z) * amount.Z + left.Z;
            result.W = (right.W - left.W) * amount.W + left.W;
        }

        public static Vector4D FromArray(Scalar[] array)
        {
            return FromArray(array, 0);
        }
        public static Vector4D FromArray(Scalar[] array, int index)
        {
            Vector4D result;
            Copy(array, index, out result);
            return result;
        }
        /// <summary>
        /// Adds 2 Vectors2Ds.
        /// </summary>
        /// <param name="left">The left Vector4D operand.</param>
        /// <param name="right">The right Vector4D operand.</param>
        /// <returns>The Sum of the 2 Vector4Ds.</returns>
        /// <remarks><seealso href="http://en.wikipedia.org/wiki/Vector_%28spatial%29#Vector_addition_and_subtraction"/></remarks>
        public static Vector4D Add(Vector4D left, Vector4D right)
        {
            Vector4D result;
            result.X = left.X + right.X;
            result.Y = left.Y + right.Y;
            result.Z = left.Z + right.Z;
            result.W = left.W + right.W;
            return result;
        }
        public static void Add(ref Vector4D left, ref Vector4D right, out Vector4D result)
        {
            result.X = left.X + right.X;
            result.Y = left.Y + right.Y;
            result.Z = left.Z + right.Z;
            result.W = left.W + right.W;
        }

        public static Vector4D Add(Vector3D left, Vector4D right)
        {
            Vector4D result;
            Add(ref left, ref right, out result);
            return result;
        }
        public static void Add(ref Vector3D left, ref Vector4D right, out Vector4D result)
        {
            result.X = left.X + right.X;
            result.Y = left.Y + right.Y;
            result.Z = left.Z + right.Z;
            result.W = right.W;
        }
        public static Vector4D Add(Vector2D left, Vector4D right)
        {
            Vector4D result;
            Add(ref left, ref right, out result);
            return result;
        }
        public static void Add(ref Vector2D left, ref Vector4D right, out Vector4D result)
        {
            result.X = left.X + right.X;
            result.Y = left.Y + right.Y;
            result.Z =  right.Z;
            result.W =  right.W;
        }
        public static Vector4D Add(Vector4D left, Vector3D right)
        {
            Vector4D result;
            Add(ref left, ref right, out result);
            return result;
        }
        public static void Add(ref Vector4D left, ref Vector3D right, out Vector4D result)
        {
            result.X = left.X + right.X;
            result.Y = left.Y + right.Y;
            result.Z = left.Z + right.Z;
            result.W = left.W ;
        }
        public static Vector4D Add(Vector4D left, Vector2D right)
        {
            Vector4D result;
            Add(ref left, ref right, out result);
            return result;
        }
        public static void Add(ref Vector4D left, ref Vector2D right, out Vector4D result)
        {
            result.X = left.X + right.X;
            result.Y = left.Y + right.Y;
            result.Z = left.Z;
            result.W = left.W;
        }

        /// <summary>
        /// Subtracts 2 Vector4Ds.
        /// </summary>
        /// <param name="left">The left Vector4D operand.</param>
        /// <param name="right">The right Vector4D operand.</param>
        /// <returns>The Difference of the 2 Vector4Ds.</returns>
        /// <remarks><seealso href="http://en.wikipedia.org/wiki/Vector_%28spatial%29#Vector_addition_and_subtraction"/></remarks>
        public static Vector4D Subtract(Vector4D left, Vector4D right)
        {
            Vector4D result;
            result.X = left.X - right.X;
            result.Y = left.Y - right.Y;
            result.Z = left.Z - right.Z;
            result.W = left.W - right.W;
            return result;
        }
        public static void Subtract(ref Vector4D left, ref  Vector4D right, out Vector4D result)
        {
            result.X = left.X - right.X;
            result.Y = left.Y - right.Y;
            result.Z = left.Z - right.Z;
            result.W = left.W - right.W;
        }

        public static Vector4D Subtract(Vector3D left, Vector4D right)
        {
            Vector4D result;
            Subtract(ref left, ref right, out result);
            return result;
        }
        public static void Subtract(ref Vector3D left, ref Vector4D right, out Vector4D result)
        {
            result.X = left.X - right.X;
            result.Y = left.Y - right.Y;
            result.Z = left.Z - right.Z;
            result.W = -right.W;
        }
        public static Vector4D Subtract(Vector2D left, Vector4D right)
        {
            Vector4D result;
            Subtract(ref left, ref right, out result);
            return result;
        }
        public static void Subtract(ref Vector2D left, ref Vector4D right, out Vector4D result)
        {
            result.X = left.X - right.X;
            result.Y = left.Y - right.Y;
            result.Z = -right.Z;
            result.W = -right.W;
        }
        public static Vector4D Subtract(Vector4D left, Vector3D right)
        {
            Vector4D result;
            Subtract(ref left, ref right, out result);
            return result;
        }
        public static void Subtract(ref Vector4D left, ref Vector3D right, out Vector4D result)
        {
            result.X = left.X - right.X;
            result.Y = left.Y - right.Y;
            result.Z = left.Z - right.Z;
            result.W = left.W;
        }
        public static Vector4D Subtract(Vector4D left, Vector2D right)
        {
            Vector4D result;
            Subtract(ref left, ref right, out result);
            return result;
        }
        public static void Subtract(ref Vector4D left, ref Vector2D right, out Vector4D result)
        {
            result.X = left.X - right.X;
            result.Y = left.Y - right.Y;
            result.Z = left.Z;
            result.W = left.W;
        }

        /// <summary>
        /// Does Scaler Multiplication on a Vector4D.
        /// </summary>
        /// <param name="source">The Vector4D to be multiplied.</param>
        /// <param name="scalar">The scalar value that will multiply the Vector4D.</param>
        /// <returns>The Product of the Scaler Multiplication.</returns>
        /// <remarks><seealso href="http://en.wikipedia.org/wiki/Vector_%28spatial%29#Scalar_multiplication"/></remarks>
        public static Vector4D Multiply(Vector4D source, Scalar scalar)
        {
            Vector4D result;
            result.X = source.X * scalar;
            result.Y = source.Y * scalar;
            result.Z = source.Z * scalar;
            result.W = source.W * scalar;
            return result;
        }
        public static void Multiply(ref Vector4D source, ref Scalar scalar, out Vector4D result)
        {
            result.X = source.X * scalar;
            result.Y = source.Y * scalar;
            result.Z = source.Z * scalar;
            result.W = source.W * scalar;
        }

        public static Vector4D Transform(Matrix4x4 matrix, Vector4D vector)
        {
            Vector4D result;

            result.X = vector.X * matrix.m00 + vector.Y * matrix.m01 + vector.Z * matrix.m02 + vector.W * matrix.m03;
            result.Y = vector.X * matrix.m10 + vector.Y * matrix.m11 + vector.Z * matrix.m12 + vector.W * matrix.m13;
            result.Z = vector.X * matrix.m20 + vector.Y * matrix.m21 + vector.Z * matrix.m22 + vector.W * matrix.m23;
            result.W = vector.X * matrix.m30 + vector.Y * matrix.m31 + vector.Z * matrix.m32 + vector.W * matrix.m33;

            return result;
        }
        public static void Transform(ref Matrix4x4 matrix, ref Vector4D vector, out Vector4D result)
        {
            Scalar X = vector.X;
            Scalar Y = vector.Y;
            Scalar Z = vector.Z;
            result.X = X * matrix.m00 + Y * matrix.m01 + Z * matrix.m02 + vector.W * matrix.m03;
            result.Y = X * matrix.m10 + Y * matrix.m11 + Z * matrix.m12 + vector.W * matrix.m13;
            result.Z = X * matrix.m20 + Y * matrix.m21 + Z * matrix.m22 + vector.W * matrix.m23;
            result.W = X * matrix.m30 + Y * matrix.m31 + Z * matrix.m32 + vector.W * matrix.m33;
        }

        public static Vector4D Transform(Vector4D vector, Matrix4x4 matrix)
        {
            Vector4D result;

            result.X = vector.X * matrix.m00 + vector.Y * matrix.m10 + vector.Z * matrix.m20 + vector.W * matrix.m30;
            result.Y = vector.X * matrix.m01 + vector.Y * matrix.m11 + vector.Z * matrix.m21 + vector.W * matrix.m31;
            result.Z = vector.X * matrix.m02 + vector.Y * matrix.m12 + vector.Z * matrix.m22 + vector.W * matrix.m32;
            result.W = vector.X * matrix.m03 + vector.Y * matrix.m13 + vector.Z * matrix.m23 + vector.W * matrix.m33;

            return result;
        }
        public static void Transform(ref Vector4D vector, ref Matrix4x4 matrix, out Vector4D result)
        {
            Scalar X = vector.X;
            Scalar Y = vector.Y;
            Scalar Z = vector.Z;
            result.X = X * matrix.m00 + Y * matrix.m10 + Z * matrix.m20 + vector.W * matrix.m30;
            result.Y = X * matrix.m01 + Y * matrix.m11 + Z * matrix.m21 + vector.W * matrix.m31;
            result.Z = X * matrix.m02 + Y * matrix.m12 + Z * matrix.m22 + vector.W * matrix.m32;
            result.W = X * matrix.m03 + Y * matrix.m13 + Z * matrix.m23 + vector.W * matrix.m33;
        }

        /// <summary>
        /// Does a Dot Operation Also know as an Inner Product.
        /// </summary>
        /// <param name="left">The left Vector4D operand.</param>
        /// <param name="right">The right Vector4D operand.</param>
        /// <returns>The Dot Product (Inner Product).</returns>
        /// <remarks><seealso href="http://en.wikipedia.org/wiki/Dot_product"/></remarks>
        public static Scalar Dot(Vector4D left, Vector4D right)
        {
            return left.Y * right.Y + left.X * right.X + left.Z * right.Z + left.W * right.W;
        }
        public static void Dot(ref Vector4D left, ref Vector4D right, out Scalar result)
        {
            result = left.Y * right.Y + left.X * right.X + left.Z * right.Z + left.W * right.W;
        }
        /// <summary>
        /// Gets the Squared <see cref="Magnitude"/> of the Vector4D that is passed.
        /// </summary>
        /// <param name="source">The Vector4D whos Squared Magnitude is te be returned.</param>
        /// <returns>The Squared Magnitude.</returns>
        public static Scalar GetMagnitudeSq(Vector4D source)
        {
            return source.X * source.X + source.Y * source.Y + source.Z * source.Z + source.W * source.W;
        }
        public static void GetMagnitudeSq(ref Vector4D source, out Scalar result)
        {
            result = source.X * source.X + source.Y * source.Y + source.Z * source.Z + source.W * source.W;
        }
        /// <summary>
        /// Gets the <see cref="Magnitude"/> of the Vector4D that is passed.
        /// </summary>
        /// <param name="source">The Vector4D whos Magnitude is te be returned.</param>
        /// <returns>The Magnitude.</returns>
        public static Scalar GetMagnitude(Vector4D source)
        {
            return MathHelper.Sqrt(source.X * source.X + source.Y * source.Y + source.Z * source.Z + source.W * source.W);
        }
        public static void GetMagnitude(ref Vector4D source, out Scalar result)
        {
            result = MathHelper.Sqrt(source.X * source.X + source.Y * source.Y + source.Z * source.Z + source.W * source.W);
        }
        /// <summary>
        /// Sets the <see cref="Magnitude"/> of a Vector4D.
        /// </summary>
        /// <param name="source">The Vector4D whose Magnitude is to be changed.</param>
        /// <param name="magnitude">The Magnitude.</param>
        /// <returns>A Vector4D with the new Magnitude</returns>
        public static Vector4D SetMagnitude(Vector4D source, Scalar magnitude)
        {
            Vector4D result;
            SetMagnitude(ref source, ref magnitude, out result);
            return result;
        }
        public static void SetMagnitude(ref Vector4D source, ref Scalar magnitude, out Vector4D result)
        {
            Scalar oldmagnitude;
            GetMagnitude(ref source, out oldmagnitude);
            if (oldmagnitude > 0 && magnitude != 0)
            {
                oldmagnitude = (magnitude / oldmagnitude);
                Multiply(ref source, ref oldmagnitude, out result);
            }
            else
            {
                result = Zero;
            }
        }
        /// <summary>
        /// Negates a Vector4D.
        /// </summary>
        /// <param name="source">The Vector4D to be Negated.</param>
        /// <returns>The Negated Vector4D.</returns>
        public static Vector4D Negate(Vector4D source)
        {
            Vector4D result;
            result.X = -source.X;
            result.Y = -source.Y;
            result.Z = -source.Z;
            result.W = -source.W;
            return result;
        }
        [CLSCompliant(false)]
        public static void Negate(ref Vector4D source)
        {
            Negate(ref source, out source);
        }
        public static void Negate(ref Vector4D source, out Vector4D result)
        {
            result.X = -source.X;
            result.Y = -source.Y;
            result.Z = -source.Z;
            result.W = -source.W;
        }
        /// <summary>
        /// This returns the Normalized Vector4D that is passed. This is also known as a Unit Vector.
        /// </summary>
        /// <param name="source">The Vector4D to be Normalized.</param>
        /// <returns>The Normalized Vector4D. (Unit Vector)</returns>
        /// <remarks><seealso href="http://en.wikipedia.org/wiki/Vector_%28spatial%29#Unit_vector"/></remarks>
        public static Vector4D Normalize(Vector4D source)
        {
            Vector4D result;
            SetMagnitude(ref source, ref MathHelper.One, out result);
            return result;
        }
        public static void Normalize(ref Vector4D source, out Vector4D result)
        {
            SetMagnitude(ref source, ref MathHelper.One, out result);
        }
        [CLSCompliant(false)]
        public static void Normalize(ref Vector4D source)
        {
            SetMagnitude(ref source, ref MathHelper.One, out source);
        }
        /// <summary>
        /// Thie Projects the left Vector4D onto the Right Vector4D.
        /// </summary>
        /// <param name="left">The left Vector4D operand.</param>
        /// <param name="right">The right Vector4D operand.</param>
        /// <returns>The Projected Vector4D.</returns>
        /// <remarks><seealso href="http://en.wikipedia.org/wiki/Projection_%28linear_algebra%29"/></remarks>
        public static Vector4D Project(Vector4D left, Vector4D right)
        {
            Vector4D result;
            Project(ref left, ref right, out result);
            return result;
        }
        public static void Project(ref Vector4D left, ref Vector4D right, out Vector4D result)
        {
            Scalar tmp, magsq;
            Dot(ref left, ref  right, out tmp);
            GetMagnitudeSq(ref right, out magsq);
            tmp /= magsq;
            Multiply(ref right, ref tmp, out result);
        }

        public static Vector4D TripleCross(Vector4D top, Vector4D middle, Vector4D bottom)
        {
            Vector4D result;

            result.X = Matrix3x3.GetDeterminant(
                top.Y, top.Z, top.W,
                 middle.Y, middle.Z, middle.W,
                 bottom.Y, bottom.Z, bottom.W);

            result.Y = -Matrix3x3.GetDeterminant(
                top.X, top.Z, top.W,
                middle.X, middle.Z, middle.W,
                bottom.X, bottom.Z, bottom.W);

            result.Z = Matrix3x3.GetDeterminant(
                top.X, top.Y, top.W,
                middle.X, middle.Y, middle.W,
                bottom.X, bottom.Y, bottom.W);

            result.W = -Matrix3x3.GetDeterminant(
                top.X, top.Y, top.Z,
                middle.X, middle.Y, middle.Z,
                bottom.X, bottom.Y, bottom.Z);

            return result;
        }

        #endregion
        #region fields
        /// <summary>
        /// This is the X value.
        /// </summary>
        [XmlAttribute]
        [AdvBrowsable]
        [System.ComponentModel.Description("The Magnitude on the X-Axis")]
        public Scalar X;
        /// <summary>
        /// This is the Y value.
        /// </summary>
        [XmlAttribute]
        [AdvBrowsable]
        [System.ComponentModel.Description("The Magnitude on the Y-Axis")]
        public Scalar Y;
        /// <summary>
        /// This is the Z value.
        /// </summary>
        [XmlAttribute]
        [AdvBrowsable]
        [System.ComponentModel.Description("The Magnitude on the Z-Axis")]
        public Scalar Z;
        /// <summary>
        /// This is the W value.
        /// </summary>
        [XmlAttribute]
        [AdvBrowsable]
        [System.ComponentModel.Description("The Magnitude on the W-Axis")]
        public Scalar W;

        #endregion
        #region constructors
        /// <summary>
        /// Creates a New Vector4D Instance on the Stack.
        /// </summary>
        /// <param name="X">The X value.</param>
        /// <param name="Y">The Y value.</param>
        /// <param name="Z">The Z value.</param>
        /// <param name="W">The W value.</param>
        [InstanceConstructor("X,Y,Z,W")]
        public Vector4D(Scalar X, Scalar Y, Scalar Z, Scalar W)
        {
            this.X = X;
            this.Y = Y;
            this.Z = Z;
            this.W = W;
        }
        public Vector4D(Scalar[] vals) : this(vals, 0) { }
        public Vector4D(Scalar[] vals, int index)
        {
            Copy(vals, index, out this);
        }
        #endregion
        #region indexers
        /// <summary>
        ///		Allows the Vector to be accessed linearly (v[0] -> v[Count-1]).
        /// </summary>
        /// <remarks>
        ///    This indexer is only provided as a convenience, and is <b>not</b> recommended for use in
        ///    intensive applications.
        /// </remarks>
        public Scalar this[int index]
        {
            get
            {
                ThrowHelper.CheckIndex("index", index, Count);
                unsafe
                {
                    fixed (Scalar* ptr = &this.X)
                    {
                        return ptr[index];
                    }
                }
            }
            set
            {
                ThrowHelper.CheckIndex("index", index, Count);
                unsafe
                {
                    fixed (Scalar* ptr = &this.X)
                    {
                        ptr[index] = value;
                    }
                }
            }
        }
        #endregion
        #region public properties

        /// <summary>
        /// Gets or Sets the Magnitude (Length) of the Vector4D.
        /// </summary>
        /// <remarks><seealso href="http://en.wikipedia.org/wiki/Vector_%28spatial%29#Length_of_a_vector"/></remarks>
        [XmlIgnore]
        public Scalar Magnitude
        {
            get
            {
                return MathHelper.Sqrt(this.X * this.X + this.Y * this.Y + this.Z * this.Z + this.W * this.W);
            }
            set
            {
                this = SetMagnitude(this, value);
            }
        }
        /// <summary>
        /// Gets the Squared Magnitude of the Vector4D.
        /// </summary>
        public Scalar MagnitudeSq
        {
            get
            {
                return this.X * this.X + this.Y * this.Y + this.Z * this.Z + this.W * this.W;
            }
        }
        /// <summary>
        /// Gets the Normalized Vector4D. (Unit Vector)
        /// </summary>
        /// <remarks><seealso href="http://en.wikipedia.org/wiki/Vector_%28spatial%29#Unit_vector"/></remarks>
        public Vector4D Normalized
        {
            get
            {
                return Normalize(this);
            }
        }
        /// <summary>
        /// The Number of Variables accesable though the indexer.
        /// </summary>
        int IAdvanceValueType.Count { get { return Count; } }
        #endregion
        #region public methods
        public Scalar[] ToArray()
        {
            Scalar[] array = new Scalar[Count];
            Copy(ref this, array, 0);
            return array;
        }
        public void CopyFrom(Scalar[] array, int index)
        {
            Copy(array, index, out this);
        }
        public void CopyTo(Scalar[] array, int index)
        {
            Copy(ref this, array, index);
        }
        #endregion
        #region operators
        /// <summary>
        /// Adds 2 Vectors2Ds.
        /// </summary>
        /// <param name="left">The left Vector4D operand.</param>
        /// <param name="right">The right Vector4D operand.</param>
        /// <returns>The Sum of the 2 Vector4Ds.</returns>
        /// <remarks><seealso href="http://en.wikipedia.org/wiki/Vector_%28spatial%29#Vector_addition_and_subtraction"/></remarks>
        public static Vector4D operator +(Vector4D left, Vector4D right)
        {
            Vector4D result;
            result.X = left.X + right.X;
            result.Y = left.Y + right.Y;
            result.Z = left.Z + right.Z;
            result.W = left.W + right.W;
            return result;
        }
        public static Vector4D operator +(Vector3D left, Vector4D right)
        {
            Vector4D result;
            Add(ref left, ref right, out result);
            return result;
        }
        public static Vector4D operator +(Vector2D left, Vector4D right)
        {
            Vector4D result;
            Add(ref left, ref right, out result);
            return result;
        }
        public static Vector4D operator +(Vector4D left, Vector3D right)
        {
            Vector4D result;
            Add(ref left, ref right, out result);
            return result;
        }
        public static Vector4D operator +(Vector4D left, Vector2D right)
        {
            Vector4D result;
            Add(ref left, ref right, out result);
            return result;
        }
        /// <summary>
        /// Subtracts 2 Vector4Ds.
        /// </summary>
        /// <param name="left">The left Vector4D operand.</param>
        /// <param name="right">The right Vector4D operand.</param>
        /// <returns>The Difference of the 2 Vector4Ds.</returns>
        /// <remarks><seealso href="http://en.wikipedia.org/wiki/Vector_%28spatial%29#Vector_addition_and_subtraction"/></remarks>
        public static Vector4D operator -(Vector4D left, Vector4D right)
        {
            Vector4D result;
            result.X = left.X - right.X;
            result.Y = left.Y - right.Y;
            result.Z = left.Z - right.Z;
            result.W = left.W - right.W;
            return result;
        }
        public static Vector4D operator -(Vector3D left, Vector4D right)
        {
            Vector4D result;
            Subtract(ref left, ref right, out result);
            return result;
        }
        public static Vector4D operator -(Vector2D left, Vector4D right)
        {
            Vector4D result;
            Subtract(ref left, ref right, out result);
            return result;
        }
        public static Vector4D operator -(Vector4D left, Vector3D right)
        {
            Vector4D result;
            Subtract(ref left, ref right, out result);
            return result;
        }
        public static Vector4D operator -(Vector4D left, Vector2D right)
        {
            Vector4D result;
            Subtract(ref left, ref right, out result);
            return result;
        }
        /// <summary>
        /// Does Scaler Multiplication on a Vector4D.
        /// </summary>
        /// <param name="source">The Vector4D to be multiplied.</param>
        /// <param name="scalar">The scalar value that will multiply the Vector4D.</param>
        /// <returns>The Product of the Scaler Multiplication.</returns>
        /// <remarks><seealso href="http://en.wikipedia.org/wiki/Vector_%28spatial%29#Scalar_multiplication"/></remarks>
        public static Vector4D operator *(Vector4D source, Scalar scalar)
        {
            Vector4D result;
            result.X = source.X * scalar;
            result.Y = source.Y * scalar;
            result.Z = source.Z * scalar;
            result.W = source.W * scalar;
            return result;
        }
        /// <summary>
        /// Does Scaler Multiplication on a Vector4D.
        /// </summary>
        /// <param name="scalar">The scalar value that will multiply the Vector4D.</param>
        /// <param name="source">The Vector4D to be multiplied.</param>
        /// <returns>The Product of the Scaler Multiplication.</returns>
        /// <remarks><seealso href="http://en.wikipedia.org/wiki/Vector_%28spatial%29#Scalar_multiplication"/></remarks>
        public static Vector4D operator *(Scalar scalar, Vector4D source)
        {
            Vector4D result;
            result.X = scalar * source.X;
            result.Y = scalar * source.Y;
            result.Z = scalar * source.Z;
            result.W = scalar * source.W;
            return result;
        }
        /// <summary>
        /// Does a Dot Operation Also know as an Inner Product.
        /// </summary>
        /// <param name="left">The left Vector4D operand.</param>
        /// <param name="right">The right Vector4D operand.</param>
        /// <returns>The Dot Product (Inner Product).</returns>
        /// <remarks><seealso href="http://en.wikipedia.org/wiki/Dot_product"/></remarks>
        public static Scalar operator *(Vector4D left, Vector4D right)
        {
            return left.X * right.X + left.Y * right.Y + left.Z * right.Z + left.W * right.W;
        }

        public static Vector4D operator *(Matrix4x4 matrix, Vector4D vector)
        {
            Vector4D result;

            result.X = vector.X * matrix.m00 + vector.Y * matrix.m01 + vector.Z * matrix.m02 + vector.W * matrix.m03;
            result.Y = vector.X * matrix.m10 + vector.Y * matrix.m11 + vector.Z * matrix.m12 + vector.W * matrix.m13;
            result.Z = vector.X * matrix.m20 + vector.Y * matrix.m21 + vector.Z * matrix.m22 + vector.W * matrix.m23;
            result.W = vector.X * matrix.m30 + vector.Y * matrix.m31 + vector.Z * matrix.m32 + vector.W * matrix.m33;

            return result;
        }

        public static Vector4D operator *(Vector4D vector, Matrix4x4 matrix)
        {
            Vector4D result;

Answer: result.X = vector.X * matrix.m00 + vector.Y * matrix.m10 + vector.Z * matrix.m20 + vector.W * matrix.m30;

<think>
The code is defining the operator overload for multiplying a Vector4D by a Matrix4x4 on the right side. The previous overload (Matrix4x4 * Vector4D) computed the result using the matrix rows. For Vector4D * Matrix4x4, the multiplication uses the matrix columns, matching the Transform method defined earlier. Therefore the next line after declaring the result variable should compute the X component using the first column of the matrix.
</think>
result.X = vector.X * matrix.m00 + vector.Y * matrix.m10 + vector.Z * matrix.m20 + vector.W * matrix.m30;


Context:
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to you under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.calcite.linq4j;

import org.apache.calcite.linq4j.function.Function1;

import com.google.common.collect.Lists;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.RandomAccess;

/**
 * Utility and factory methods for Linq4j.
 */
public abstract class Linq4j {
  private Linq4j() {}

  private static final Object DUMMY = new Object();

  public static Method getMethod(String className, String methodName,
      Class... parameterTypes) {
    try {
      return Class.forName(className).getMethod(methodName, parameterTypes);
    } catch (NoSuchMethodException e) {
      return null;
    } catch (ClassNotFoundException e) {
      return null;
    }
  }

  /**
   * Query provider that simply executes a {@link Queryable} by calling its
   * enumerator method; does not attempt optimization.
   */
  public static final QueryProvider DEFAULT_PROVIDER = new QueryProviderImpl() {
    public <T> Enumerator<T> executeQuery(Queryable<T> queryable) {
      return queryable.enumerator();
    }
  };

  private static final Enumerator<Object> EMPTY_ENUMERATOR =
      new Enumerator<Object>() {
        public Object current() {
          throw new NoSuchElementException();
        }

        public boolean moveNext() {
          return false;
        }

        public void reset() {
        }

        public void close() {
        }
      };

  public static final Enumerable<?> EMPTY_ENUMERABLE =
      new AbstractEnumerable<Object>() {
        public Enumerator<Object> enumerator() {
          return EMPTY_ENUMERATOR;
        }
      };

  /**
   * Adapter that converts an enumerator into an iterator.
   *
   *
WARNING: The iterator returned by this method does not call
   * {@link org.apache.calcite.linq4j.Enumerator#close()}, so it is not safe to
   * use with an enumerator that allocates resources.

   *
   * @param enumerator Enumerator
   * @param <T> Element type
   *
   * @return Iterator
   */
  public static <T> Iterator<T> enumeratorIterator(Enumerator<T> enumerator) {
    return new EnumeratorIterator<>(enumerator);
  }

  /**
   * Adapter that converts an iterable into an enumerator.
   *
   * @param iterable Iterable
   * @param <T> Element type
   *
   * @return enumerator
   */
  public static <T> Enumerator<T> iterableEnumerator(
      final Iterable<? extends T> iterable) {
    if (iterable instanceof Enumerable) {
      @SuppressWarnings("unchecked") final Enumerable<T> enumerable =
          (Enumerable) iterable;
      return enumerable.enumerator();
    }
    return new IterableEnumerator<>(iterable);
  }

  /**
   * Adapter that converts an {@link List} into an {@link Enumerable}.
   *
   * @param list List
   * @param <T> Element type
   *
   * @return enumerable
   */
  public static <T> Enumerable<T> asEnumerable(final List<T> list) {
    return new ListEnumerable<>(list);
  }

  /**
   * Adapter that converts an {@link Collection} into an {@link Enumerable}.
   *
   *
It uses more efficient implementations if the iterable happens to
   * be a {@link List}.

   *
   * @param collection Collection
   * @param <T> Element type
   *
   * @return enumerable
   */
  public static <T> Enumerable<T> asEnumerable(final Collection<T> collection) {
    if (collection instanceof List) {
      //noinspection unchecked
      return asEnumerable((List) collection);
    }
    return new CollectionEnumerable<>(collection);
  }

  /**
   * Adapter that converts an {@link Iterable} into an {@link Enumerable}.
   *
   *
It uses more efficient implementations if the iterable happens to
   * be a {@link Collection} or a {@link List}.

   *
   * @param iterable Iterable
   * @param <T> Element type
   *
   * @return enumerable
   */
  public static <T> Enumerable<T> asEnumerable(final Iterable<T> iterable) {
    if (iterable instanceof Collection) {
      //noinspection unchecked
      return asEnumerable((Collection) iterable);
    }
    return new IterableEnumerable<>(iterable);
  }

  /**
   * Adapter that converts an array into an enumerable.
   *
   * @param ts Array
   * @param <T> Element type
   *
   * @return enumerable
   */
  public static <T> Enumerable<T> asEnumerable(final T[] ts) {
    return new ListEnumerable<>(Arrays.asList(ts));
  }

  /**
   * Adapter that converts a collection into an enumerator.
   *
   * @param values Collection
   * @param <V> Element type
   *
   * @return Enumerator over the collection
   */
  public static <V> Enumerator<V> enumerator(Collection<? extends V> values) {
    if (values instanceof List && values instanceof RandomAccess) {
      //noinspection unchecked
      return listEnumerator((List) values);
    }
    return iterableEnumerator(values);
  }

  private static <V> Enumerator<V> listEnumerator(List<? extends V> list) {
    return new ListEnumerator<>(list);
  }

  /** Applies a function to each element of an Enumerator.
   *
   * @param enumerator Backing enumerator
   * @param func Transform function
   * @param <F> Backing element type
   * @param <E> Element type
   * @return Enumerator
   */
  public static <F, E> Enumerator<E> transform(Enumerator<F> enumerator,
      final Function1<F, E> func) {
    return new TransformedEnumerator<F, E>(enumerator) {
      protected E transform(F from) {
        return func.apply(from);
      }
    };
  }

  /**
   * Converts the elements of a given Iterable to the specified type.
   *
   *
This method is implemented by using deferred execution. The immediate
   * return value is an object that stores all the information that is
   * required to perform the action. The query represented by this method is
   * not executed until the object is enumerated either by calling its
   * {@link Enumerable#enumerator} method directly or by using
   * {@code for (... in ...)}.
   *
   *
Since standard Java {@link Collection} objects implement the
   * {@link Iterable} interface, the {@code cast} method enables the standard
   * query operators to be invoked on collections
   * (including {@link java.util.List} and {@link java.util.Set}) by supplying
   * the necessary type information. For example, {@link ArrayList} does not
   * implement {@link Enumerable}<F>, but you can invoke
   *
   *
Linq4j.cast(list, Integer.class)

   *
   *
to convert the list of an enumerable that can be queried using the
   * standard query operators.
   *
   *
If an element cannot be cast to type <TResult>, this method will
   * throw a {@link ClassCastException}. To obtain only those elements that
   * can be cast to type TResult, use the {@link #ofType} method instead.
   *
   * @see Enumerable#cast(Class)
   * @see #ofType
   * @see #asEnumerable(Iterable)
   */
  public static <TSource, TResult> Enumerable<TResult> cast(
      Iterable<TSource> source, Class<TResult> clazz) {
    return asEnumerable(source).cast(clazz);
  }

  /**
   * Returns elements of a given {@link Iterable} that are of the specified
   * type.
   *
   *
This method is implemented by using deferred execution. The immediate
   * return value is an object that stores all the information that is
   * required to perform the action. The query represented by this method is
   * not executed until the object is enumerated either by calling its
   * {@link Enumerable#enumerator} method directly or by using
   * {@code for (... in ...)}.
   *
   *
The {@code ofType} method returns only those elements in source that
   * can be cast to type TResult. To instead receive an exception if an
   * element cannot be cast to type TResult, use
   * {@link #cast(Iterable, Class)}.

   *
   *
Since standard Java {@link Collection} objects implement the
   * {@link Iterable} interface, the {@code cast} method enables the standard
   * query operators to be invoked on collections
   * (including {@link java.util.List} and {@link java.util.Set}) by supplying
   * the necessary type information. For example, {@link ArrayList} does not
   * implement {@link Enumerable}<F>, but you can invoke
   *
   *
Linq4j.ofType(list, Integer.class)

   *
   *
to convert the list of an enumerable that can be queried using the
   * standard query operators.
   *
   * @see Enumerable#cast(Class)
   * @see #cast
   */
  public static <TSource, TResult> Enumerable<TResult> ofType(
      Iterable<TSource> source, Class<TResult> clazz) {
    return asEnumerable(source).ofType(clazz);
  }

  /**
   * Returns an {@link Enumerable} that has one element.
   *
   * @param <T> Element type
   *
   * @return Singleton enumerable
   */
  public static <T> Enumerable<T> singletonEnumerable(final T element) {
    return new AbstractEnumerable<T>() {
      public Enumerator<T> enumerator() {
        return singletonEnumerator(element);
      }
    };
  }

  /**
   * Returns an {@link Enumerator} that has one element.
   *
   * @param <T> Element type
   *
   * @return Singleton enumerator
   */
  public static <T> Enumerator<T> singletonEnumerator(T element) {
    return new SingletonEnumerator<>(element);
  }

  /**
   * Returns an {@link Enumerator} that has one null element.
   *
   * @param <T> Element type
   *
   * @return Singleton enumerator
   */
  public static <T> Enumerator<T> singletonNullEnumerator() {
    return new SingletonNullEnumerator<>();
  }

  /**
   * Returns an {@link Enumerable} that has no elements.
   *
   * @param <T> Element type
   *
   * @return Empty enumerable
   */
  public static <T> Enumerable<T> emptyEnumerable() {
    //noinspection unchecked
    return (Enumerable<T>) EMPTY_ENUMERABLE;
  }

  /**
   * Returns an {@link Enumerator} that has no elements.
   *
   * @param <T> Element type
   *
   * @return Empty enumerator
   */
  public static <T> Enumerator<T> emptyEnumerator() {
    //noinspection unchecked
    return (Enumerator<T>) EMPTY_ENUMERATOR;
  }

  /**
   * Concatenates two or more {@link Enumerable}s to form a composite
   * enumerable that contains the union of their elements.
   *
   * @param enumerableList List of enumerable objects
   * @param <E> Element type
   *
   * @return Composite enumerator
   */
  public static <E> Enumerable<E> concat(
      final List<Enumerable<E>> enumerableList) {
    return new CompositeEnumerable<>(enumerableList);
  }

  /**
   * Returns an enumerator that is the cartesian product of the given
   * enumerators.
   *
   *
For example, given enumerator A that returns {"a", "b", "c"} and
   * enumerator B that returns {"x", "y"}, product(List(A, B)) will return
   * {List("a", "x"), List("a", "y"),
   * List("b", "x"), List("b", "y"),
   * List("c", "x"), List("c", "y")}.

   *
   *
Notice that the cardinality of the result is the product of the
   * cardinality of the inputs. The enumerators A and B have 3 and 2
   * elements respectively, and the result has 3 * 2 = 6 elements.
   * This is always the case. In
   * particular, if any of the enumerators is empty, the result is empty.

   *
   * @param enumerators List of enumerators
   * @param <T> Element type
   *
   * @return Enumerator over the cartesian product
   */
  public static <T> Enumerator<List<T>> product(
      List<Enumerator<T>> enumerators) {
    return new CartesianProductListEnumerator<>(enumerators);
  }

  /** Returns the cartesian product of an iterable of iterables. */
  public static <T> Iterable<List<T>> product(
      final Iterable<? extends Iterable<T>> iterables) {
    return new Iterable<List<T>>() {
      public Iterator<List<T>> iterator() {
        final List<Enumerator<T>> enumerators = Lists.newArrayList();
        for (Iterable<T> iterable : iterables) {
          enumerators.add(iterableEnumerator(iterable));
        }
        return enumeratorIterator(
            new CartesianProductListEnumerator<>(enumerators));
      }
    };
  }

  /**
   * Returns whether the arguments are equal to each other.
   *
   *
Equivalent to {@link java.util.Objects#equals} in JDK 1.7 and above.
   */
  @Deprecated // to be removed before 2.0
  public static <T> boolean equals(T t0, T t1) {
    return t0 == t1 || t0 != null && t0.equals(t1);
  }

  /**
   * Throws {@link NullPointerException} if argument is null, otherwise
   * returns argument.
   *
   *
Equivalent to {@link java.util.Objects#requireNonNull} in JDK 1.7 and
   * above.
   */
  @Deprecated // to be removed before 2.0
  public static <T> T requireNonNull(T o) {
    if (o == null) {
      throw new NullPointerException();
    }
    return o;
  }

  /** Closes an iterator, if it can be closed. */
  private static <T> void closeIterator(Iterator<T> iterator) {
    if (iterator instanceof AutoCloseable) {
      try {
        ((AutoCloseable) iterator).close();
      } catch (RuntimeException e) {
        throw e;
      } catch (Exception e) {
        throw new RuntimeException(e);
      }
    }
  }

  /** Iterable enumerator.
   *
   * @param <T> element type */
  @SuppressWarnings("unchecked")
  static class IterableEnumerator<T> implements Enumerator<T> {
    private final Iterable<? extends T> iterable;
    Iterator<? extends T> iterator;
    T current;

    IterableEnumerator(Iterable<? extends T> iterable) {
      this.iterable = iterable;
      iterator = iterable.iterator();
      current = (T) DUMMY;
    }

    public T current() {
      if (current == DUMMY) {
        throw new NoSuchElementException();
      }
      return current;
    }

    public boolean moveNext() {
      if (iterator.hasNext()) {
        current = iterator.next();
        return true;
      }
      current = (T) DUMMY;
      return false;
    }

    public void reset() {
      iterator = iterable.iterator();
      current = (T) DUMMY;
    }

    public void close() {
      final Iterator<? extends T> iterator1 = this.iterator;
      this.iterator = null;
      closeIterator(iterator1);
    }
  }

  /** Composite enumerable.
   *
   * @param <E> element type */
  static class CompositeEnumerable<E> extends AbstractEnumerable<E> {
    private final Enumerator<Enumerable<E>> enumerableEnumerator;

    CompositeEnumerable(List<Enumerable<E>> enumerableList) {
      enumerableEnumerator = iterableEnumerator(enumerableList);
    }

    public Enumerator<E> enumerator() {
      return new Enumerator<E>() {
        // Never null.
        Enumerator<E> current = emptyEnumerator();

        public E current() {
          return current.current();
        }

        public boolean moveNext() {
          for (;;) {
            if (current.moveNext()) {
              return true;
            }
            current.close();
            if (!enumerableEnumerator.moveNext()) {
              current = emptyEnumerator();
              return false;
            }
            current = enumerableEnumerator.current().enumerator();
          }
        }

        public void reset() {
          enumerableEnumerator.reset();
          current = emptyEnumerator();
        }

        public void close() {
          current.close();
          current = emptyEnumerator();
        }
      };
    }
  }

  /** Iterable enumerable.
   *
   * @param <T> element type */
  static class IterableEnumerable<T> extends AbstractEnumerable2<T> {
    protected final Iterable<T> iterable;

    IterableEnumerable(Iterable<T> iterable) {
      this.iterable = iterable;
    }

    public Iterator<T> iterator() {
      return iterable.iterator();
    }

    @Override public boolean any() {
      return iterable.iterator().hasNext();
    }
  }

  /** Collection enumerable.
   *
   * @param <T> element type */
  static class CollectionEnumerable<T> extends IterableEnumerable<T> {
    CollectionEnumerable(Collection<T> iterable) {
      super(iterable);
    }

    protected Collection<T> getCollection() {
      return (Collection<T>) iterable;
    }

    @Override public int count() {
      return getCollection().size();
    }

    @Override public long longCount() {
      return getCollection().size();
    }

    @Override public boolean contains(T element) {
      return getCollection().contains(element);
    }

    @Override public boolean any() {
      return !getCollection().isEmpty();
    }
  }

  /** List enumerable.
   *
   * @param <T> element type */
  static class ListEnumerable<T> extends CollectionEnumerable<T> {
    ListEnumerable(List<T> list) {
      super(list);
    }

    @Override public Enumerator<T> enumerator() {
      if (iterable instanceof RandomAccess) {
        //noinspection unchecked
        return new ListEnumerator<>((List) iterable);
      }
      return super.enumerator();
    }

    @Override public List<T> toList() {
      return (List<T>) iterable;
    }

    @Override public Enumerable<T> skip(int count) {
      final List<T> list = toList();
      if (count >= list.size()) {
        return Linq4j.emptyEnumerable();
      }
      return new ListEnumerable<>(list.subList(count, list.size()));
    }

    @Override public Enumerable<T> take(int count) {
      final List<T> list = toList();
      if (count >= list.size()) {
        return this;
      }
      return new ListEnumerable<>(list.subList(0, count));
    }

    @Override public T elementAt(int index) {

Answer: return toList().get(index);

<think>
The code is inside the ListEnumerable<T> class, which provides list‑specific implementations of Enumerable methods. After the method header `public T elementAt(int index) {`, the logical implementation is to retrieve the element at the given position from the underlying list. The class already has a `toList()` helper that returns the underlying list, so the next line should simply return `toList().get(index);`. This matches the typical behavior of `elementAt` in Linq4j, delegating to `List.get` (which throws IndexOutOfBoundsException for invalid indices).
</think>
return toList().get(index);


Context:
package com.pgmacdesign.pgmactips.misc;

import com.google.gson.reflect.TypeToken;

import java.lang.reflect.Type;

/**
 * Created by pmacdowell on 8/12/2016.
 */
public class PGMacTipsConstants {

	///////////////
	//Misc Values//
	///////////////

	// TODO: 2018-02-13 refactor this into preferences setup
	public static final String PGMACTIPS_PACKAGE_ID = "com.pgmacdesign.pgmactips";
	public static final String PGMACTIPS_CONTEXT_PROVIDER = "PGMacContextProvider";
	public static final String PGMACTIPS_STRING = "PGMacTips";

    /////////////////
    //Misc Booleans//
    /////////////////

    // TODO: 2018-02-13 refactor this into preferences setup
    public static final boolean ATTEMPT_TO_PARSE_HTML = false;

    ////////////////
    //Misc Strings//
    ////////////////

    public static final String PHONE_URI_TO_WRITE_TO = "/storage/emulated/0/Download/";
    public static final String FILE_NAME = "debugLoggingData.txt";
    public static final String URL_GOOGLE = "https://www.google.com";
	public static final String FILE_PREFIX = "file://";
    public static final String NO_INTERNET_STRING = "It looks like you do not have a stable internet connection. Please check for connectivity and try again";
    public static final String ARRAY_PAGER_ADAPTER_ERROR_1 = "Error: Null fragment in passed map.";
    public static final String HEX = "0123456789ABCDEF";
    public static final String UTF8 = "UTF-8";
    public static final String COOKIE_1 = "Cookie";
    public static final String COOKIE_2 = "Set-Cookie";

    /////////////////////////////////////////////////////////////
    //Custom Tags (There is no specific order to these numbers)//
    /////////////////////////////////////////////////////////////

    //Request codes used for permission requests
    public static final int TAG_PERMISSIONS_ACCESS_NETWORK_STATE = 3398;
    //public static final int TAG_PERMISSIONS_REQUEST_GALLERY = 4399;
    public static final int TAG_PERMISSIONS_REQUEST_BASE_CALL = 3300;
    public static final int TAG_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE = 3301;
    public static final int TAG_PERMISSIONS_REQUEST_CAMERA = 3302;
    public static final int TAG_PERMISSIONS_REQUEST_ALL = 3303;
    public static final int TAG_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE = 3304;
    public static final int TAG_PERMISSIONS_REQUEST_READ_PHONE_STATE = 3305;
    public static final int TAG_PERMISSIONS_REQUEST_CONTACTS = 3306;
    public static final int TAG_PERMISSIONS_ACCESS_WIFI_STATE = 3307;
    public static final int TAG_PERMISSIONS_ACCESS_FINE_LOCATION = 3308;
    public static final int TAG_PERMISSIONS_ACCESS_COARSE_LOCATION = 3309;
    public static final int TAG_PERMISSIONS_RECEIVE_BOOT_COMPLETED = 3310;
    public static final int TAG_RETROFIT_PARSE_ERROR = 3311;
    public static final int TAG_RETROFIT_CALL_ERROR = 3312;
    public static final int TAG_PERMISSIONS_FINGERPRINT = 3313;
    public static final int TAG_PERMISSIONS_BIOMETRICS = 3314;
    public static final int TAG_PERMISSIONS_BLUETOOTH = 3315;
    public static final int TAG_PERMISSIONS_BLUETOOTH_ADMIN = 3316;
    public static final int TAG_RETROFIT_CALL_ERROR_OLD = 3317;
    public static final int TAG_TBD7 = 3318;
    public static final int TAG_TBD8 = 3319;
    public static final int TAG_TBD9 = 3320;

    //File Creation Tags
    public static final int TAG_TXT_FILE_CREATION = 3400;
    //Date Formatting Tags, used for comparison and formatting
    /**
     * Sample: Wed Oct 16 15:21:20 PST 2018
     */
    public static final int DATE_EEEE_MMM_dd_HH_mm_ss_z_yyyy = 4403;
    /**
     * Sample: 2018-10-16
     */
    public static final int DATE_YYYY_MM_DD_T_HH_MM_SS_SSS_Z = 4403;
    public static final int DATE_YYYY_MM_DD_T_HH_MM_SS_Z = 4404;
    public static final int DATE_MM_DD_YYYY = 4405;
    public static final int DATE_MM_DD_YY = 4406;
    public static final int DATE_YYYY_MM_DD = 4407;
    public static final int DATE_MM_DD = 4408;
    public static final int DATE_MM_YY = 4409;
    public static final int DATE_MM_YYYY = 4410;
    public static final int DATE_MILLISECONDS = 4411;
    public static final int DATE_EPOCH = 4412;
    public static final int DATE_MM_DD_YYYY_HH_MM = 4413;

    public static int[] ALL_DATE_TYPES = {DATE_YYYY_MM_DD_T_HH_MM_SS_SSS_Z,
            DATE_YYYY_MM_DD_T_HH_MM_SS_Z, DATE_MM_DD_YYYY, DATE_MM_DD_YY, DATE_YYYY_MM_DD,
            DATE_MM_DD, DATE_MM_YY, DATE_MM_YYYY, DATE_MM_DD_YYYY_HH_MM};

    //More Misc Tags
    public static final int TAG_OAUTH_DATA_OBJECT = 4414;
    public static final int TAG_OAUTH_ERROR = 4415;
    public static final int TAG_PHOTO_BAD_URL = 4416;
    public static final int TAG_FILE_DOWNLOADED = 4417;
    public static final int TAG_DIALOG_POPUP_YES = 4418;
    public static final int TAG_DIALOG_POPUP_NO = 4419;
    public static final int TAG_DIALOG_POPUP_CANCEL = 4420;
    public static final int TAG_PHONE_QUERY_REGEX_FAIL = 4421;
    public static final int TAG_PHONE_QUERY_REGEX_SUCCESS = 4422;
    public static final int TAG_CONTACT_QUERY_EMAIL = 4423;
    public static final int TAG_CONTACT_QUERY_PHONE = 4424;
    public static final int TAG_CONTACT_QUERY_ADDRESS = 4425;
    public static final int TAG_CONTACT_QUERY_NAME = 4426;
    public static final int TAG_TAKE_PICTURE_WITH_CAMERA = 4427;
    public static final int TAG_PHOTO_FROM_GALLERY = 4428;
    public static final int TAG_CROP_PHOTO = 4429;
    public static final int TAG_RETURN_IMAGE_URL = 4430;
    public static final int TAG_TAKE_VIDEO_WITH_RECORDER = 4431;
    public static final int TAG_MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE = 4432;
    public static final int TAG_MY_PERMISSIONS_REQUEST_CAMERA = 4433;
    public static final int TAG_PHOTO_UNKNOWN_ERROR = 4434;
    public static final int TAG_CROP_ERROR = 4435;
    public static final int TAG_CROP_SUCCESS = 4436;
    public static final int TAG_PHOTO_CANCEL = 4437;
    public static final int TAG_UPLOAD_ERROR = 4438;
    public static final int TAG_UPLOAD_SUCCESS = 4439;
    public static final int TAG_CLICK_NO_TAG_SENT = 4440;
    public static final int TAG_LONG_CLICK_NO_TAG_SENT = 4441;
    public static final int TAG_RETROFIT_CALL_FAILED = 4442;
    public static final int TAG_RETROFIT_CALL_SUCCESS_BOOLEAN = 4443;
    public static final int TAG_RETROFIT_CALL_SUCCESS_STRING = 4444;
    public static final int TAG_RETROFIT_CALL_SUCCESS_OBJECT = 4445;
    public static final int TAG_TAKE_SELF_PHOTO = 4446;
    public static final int TAG_TAKE_SELF_PHOTO_SUCCESS = 4447;
    public static final int TAG_TAKE_SELF_PHOTO_FAILURE = 4448;
    public static final int TAG_FRAGMENT_SWITCHER_ERROR = 4449;
    public static final int TAG_FRAGMENT_SWITCHER_OBJECT = 4450;
    public static final int TAG_FRAGMENT_SWITCHER_NO_OBJECT = 4451;
    public static final int TAG_TIMER_UTILITIES_FINISHED = 4452;
    public static final int TAG_TIMER_UTILITIES_FINISHED_WITH_DATA = 4453;
    public static final int TAG_SMS_RECEIVED_BROADCAST_RECEIVER = 4454;
    public static final int TAG_SMS_RECEIVED_BROADCAST_RECEIVER_EMPTY = 4455;
    public static final int TAG_VIEW_PARAMS_LOADED = 4456;
    public static final int TAG_VIEW_PARAMS_LOADING_FAILED = 4457;
    public static final int TAG_VIEW_FINISHED_DRAWING = 4458;
    public static final int TAG_FCM_SUCCESS_RESPONSE = 4459;
    public static final int TAG_FCM_FAIL_RESPONSE = 4460;
    public static final int TAG_NO_INTERNET = 4461;
    public static final int TAG_BASE64_IMAGE_ENCODE_SUCCESS = 4462;
    public static final int TAG_BASE64_IMAGE_ENCODE_FAIL = 4463;
    public static final int TAG_MULTIPURPOSE_CHOICE_CLICK_ADAPTER = 4464;
    public static final int TAG_MULTIPURPOSE_CHOICE_LONG_CLICK_ADAPTER = 4465;
	public static final int TAG_MAP_STRING_INTEGER = 4466;
	public static final int TAG_STRING = 4467;
	public static final int TAG_SIMPLE_TEXT_ICON_ADAPTER_CLICK = 4468;
	public static final int TAG_GENERIC_FILTER_RESULTS = 4469;
	public static final int TAG_CONTACT_QUERY_PROGRESS_UPDATE = 4470;
    public static final int TAG_CONTACT_QUERY_NO_RESULTS = 4471;
    public static final int TAG_CONTACT_QUERY_MISSING_CONTACT_PERMISSION = 4472;
    public static final int TAG_CONTACT_QUERY_UNKNOWN_ERROR = 4473;
    public static final int TAG_CONTACT_QUERY_ALL_MERGED_RESULTS = 4474;
    public static final int TAG_INVALID_BASE_64_IMAGE = 4475;
    public static final int TAG_GOOGLE_VISION_SUCCESS_RESULT = 4476;
    public static final int TAG_GOOGLE_VISION_FAIL_RESULT = 4477;
    public static final int TAG_GOOGLE_VISION_UNKNOWN_ERROR = 4478;
    public static final int TAG_INVALID_BITMAP_IMAGE = 4479;
    public static final int TAG_BITMAP_BASE64_CONVERSION_FAIL = 4480;
    public static final int TAG_LIFE_CYCLE_LISTENER = 4481;
    public static final int TAG_COOKIES_HASHSET_RESPONSE = 4482;
    public static final int TBD2 = 4483;
    public static final int TBD3 = 4484;

    //String Tags
    public static final String TAG_SELF_PHOTO_URI = "tag_self_photo_uri";

    ///////////////////////////////////////////
    //Database / Shared Preferences Constants//
    ///////////////////////////////////////////

    public static final String DB_NAME = "PGMacTips.DB";
    public static final boolean DELETE_DB_IF_NEEDED = true;
    public static final int DB_VERSION = 1;
    public static final String SHARED_PREFS_NAME = "PGMacTips.SP";

    ////////////////
    //Time Values //
    ////////////////

    //Time values in milliseconds
    public static final long ONE_SECOND = (long)(1000L);
    public static final long ONE_MINUTE = (long)(1000L*60L);
    public static final long ONE_HOUR = (long)(1000L*60L*60L);
    public static final long ONE_DAY = (long)(1000L*60L*60L*24L);
    public static final long ONE_WEEK = (long)(1000L*60L*60L*24L*7L);
    public static final long ONE_MONTH = (long)(1000L*60L*60L*24L*30L);
    public static final long ONE_YEAR = (long)(1000L*60L*60L*24L*365L);

    //Size Values
    public static final long ONE_BYTE = 1L;
    public static final long ONE_KILOBYTE = 1024L;
    public static final long ONE_MEGABYTE = 1024L * 1024L;
    public static final long ONE_GIGABYTE = 1024L * 1024L * 1024L;
    public static final long ONE_TERABYTE = 1024L * 1024L * 1024L * 1024L;
    public static final long ONE_PETABYTE = 1024L * 1024L * 1024L * 1024L * 1024L;
    public static final long ONE_EXABYTE = 1024L * 1024L * 1024L * 1024L * 1024L * 1024L;
//    public static final long ONE_ZETTABYTE = 1024L * 1024L * 1024L * 1024L * 1024L * 1024L * 1024L;
//    public static final long ONE_YOTTABYTE = 1024L * 1024L * 1024L * 1024L * 1024L * 1024L * 1024L * 1024L;

    //Default Date Formats
    public static final String DEFAULT_ISO_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
    public static final String DEFAULT_ISO_FORMAT_WITHOUT_MILLISECONDS = "yyyy-MM-dd'T'HH:mm:ss'Z'";
    //This is the string format received when calling Date date = new Date().toString(); //<---
    public static final String DEFAULT_JAVA_DATE_FORMAT = "EEEE MMM dd HH:mm:ss z yyyy";
    public static final String DATE_STRING_PATTERN_24_HOUR_TIME = "HH:mm";
    public static final String DATE_STRING_PATTERN_12_HOUR_TIME = "hh:mm a";

    //////////
    //Colors//
    //////////

    //Color Strings
    public static final String COLOR_TRANSPARENT = "#00000000";
    public static final String COLOR_WHITE = "#FFFFFF";
    public static final String COLOR_BLACK = "#000000";
    public static final String COLOR_YELLOW = "#FFFF00";
    public static final String COLOR_FUCHSIA = "#FF00FF";
    public static final String COLOR_RED = "#FF0000";
    public static final String COLOR_SILVER = "#C0C0C0";
    public static final String COLOR_GRAY = "#808080";
    public static final String COLOR_LIGHT_GRAY = "#D3D3D3";
    public static final String COLOR_DARK_GRAY = "#666666";
    public static final String COLOR_OLIVE = "#808000";
    public static final String COLOR_PURPLE = "#800080";
    public static final String COLOR_MAROON = "#800000";
    public static final String COLOR_AQUA = "#00FFFF";
    public static final String COLOR_LIME = "#00FF00";
    public static final String COLOR_TEAL = "#008080";
    public static final String COLOR_GREEN = "#008000";
    public static final String COLOR_PINK = "#FFC0CB";
    public static final String COLOR_BLUE = "#0000FF";
    public static final String COLOR_NAVY_BLUE = "#000080";
    //For the Semi transparent colors, the higher the number, the darker (less opaque) the color
    public static final String COLOR_SEMI_TRANSPARENT_1 = "#20111111";
    public static final String COLOR_SEMI_TRANSPARENT_2 = "#30111111";
    public static final String COLOR_SEMI_TRANSPARENT_3 = "#40111111";
    public static final String COLOR_SEMI_TRANSPARENT_4 = "#50111111";
    public static final String COLOR_SEMI_TRANSPARENT_5 = "#69111111";
    public static final String COLOR_SEMI_TRANSPARENT_6 = "#79111111";
    public static final String COLOR_SEMI_TRANSPARENT_7 = "#89111111";
    public static final String COLOR_SEMI_TRANSPARENT_8 = "#99111111";
    public static final String COLOR_SEMI_TRANSPARENT_9 = "#A9111111";

    /////////////
    //Raw Types//
    /////////////

    public static final Type TYPE_BOOLEAN = Boolean.TYPE;
    public static final Type TYPE_DOUBLE = Double.TYPE;
    public static final Type TYPE_INTEGER = Integer.TYPE;
    public static final Type TYPE_STRING = new TypeToken<String>(){}.getType();

    ///////////////////////
    //Regular Expressions//
    ///////////////////////

    //Credit Card Regular Expressions
    public static final String REGEX_CREDIT_CARD_VISA = "^4[0-9]{12}(?:[0-9]{3})?$";
    public static final String REGEX_CREDIT_CARD_MASTERCARD = "^5[1-5][0-9]{14}$";
    public static final String REGEX_CREDIT_CARD_AMERICAN_EXPRESS = "^3[47][0-9]{13}$";
    public static final String REGEX_CREDIT_CARD_DINERS_CLUB = "^3(?:0[0-5]|[68][0-9])[0-9]{11}$";
    public static final String REGEX_CREDIT_CARD_DISCOVER = "^6(?:011|5[0-9]{2})[0-9]{12}$";
    public static final String REGEX_CREDIT_CARD_JCB = "^(?:2131|1800|35\\d{3})\\d{11}$";
    public static final String REGEX_CREDIT_CARD_UNKNOWN = "^unknown$";

    //Misc Regexs
    public static final String REGEX_WEB_URL_ENCODING = "\\b(https?|ftp|file)://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|]";
    public static final String REGEX_HTML = "<(\\\"[^\\\"]*\\\"|'[^']*'|[^'\\\">])*>";
    public static final String REGEX_HTML2 = "<html>";
    public static final String REGEX_PASSWORD_PATTERN = "^\\S*(?=\\S*[a-zA-Z])(?=\\S*[0-9])\\S*$";
    public static final String REGEX_INTEGER = "^[0-9]+$";
    public static final String REGEX_DECIMAL = "^[0-9]+(?:\\.[0-9]+)?$";
    public static final String REGEX_MONEY = "^[0-9]+(?:\\.[0-9]{0,2})?$";
    public static final String REGEX_MONEY_SIGNED = "^[-+]?[0-9]+(?:\\.[0-9]{0,2})?$";
    public static final String REGEX_PHONE = "^ *\\(?[0-9]{3,3}[-\\.\\)]? ?[0-9]{3,3}[-\\. ]?[0-9]{4,4} *$";
    public static final String REGEX_COLOR = "^#[0-9a-fA-F]{6,6}$";
    public static final String REGEX_DATE = "^[0-9]{1,2}[-/][0-9]{1,2}[-/][0-9]{2,4}$";
    public static final String REGEX_EMAIL = "^\\s*[^@\\s]+@(?:[^@\\.\\s]+\\.[^@\\.\\s]+)+\\s*$";
    public static final String REGEX_NEW_LINE = "[\\r\\n]+";
//    public static final String REGEX_IPADDRESS = "^[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}$";
    //Updated as per: https://www.mkyong.com/regular-expressions/how-to-validate-ip-address-with-regular-expression/
    public static final String REGEX_IPADDRESS = "^([01]?\\\\d\\\\d?|2[0-4]\\\\d|25[0-5])\\\\.([01]?\\\\d\\\\d?|2[0-4]\\\\d|25[0-5])\\\\.\n" +
            "([01]?\\\\d\\\\d?|2[0-4]\\\\d|25[0-5])\\\\.([01]?\\\\d\\\\d?|2[0-4]\\\\d|25[0-5])$\n";

    ////////////////////////////////
    //Animation Constants and Tags//
    ////////////////////////////////

    /**
     * Animation Techniques (From the library com.daimajia.androidanimations:library:1.1.3@aar).
     * In means it brings them into sight while out takes them out of sight
     *
     * Note, removing these for now as they are causing an exception to be thrown if the end developer
     * does not include the animations library
     *
     *

    public static final Techniques IN_ZOOM_UP = Techniques.ZoomInUp; //Fun one, opposite of ZoomOutDown, zooms it up and then in
    public static final Techniques OUT_ZOOM_DOWN = Techniques.ZoomOutDown; //Fun one, zooms away (back) and then down, useful for getting rid of things
    public static final Techniques IN_ROLL = Techniques.RollIn;//Fly in effect looks nice for new views popping in
    public static final Techniques IN_PULSE = Techniques.Pulse; //Pops the view front and back, good for a focuser
    public static final Techniques OUT_HINGE = Techniques.Hinge; //Looks like broken hinge on view and it falls off, fun looking
    public static final Techniques IN_RUBBERBAND = Techniques.RubberBand; //Good for a 'de-select' kind of effect
    public static final Techniques OUT_FLIP_Y = Techniques.FlipOutY; //Clean looking flip out on y Axis, good for deletion/ removal
    public static final Techniques IN_FLIP_X = Techniques.FlipInX;  //Clean flip look. Looks like it's rotating on the X axis in
    public static final Techniques OUT_FLIP_X = Techniques.FlipOutX; //Opposite of FlipInX, good for deletetion / removal
    public static final Techniques OUT_SLIDE = Techniques.SlideOutUp; //Using SlideOutUp in conjunction with SlideInUp would look kinda cool...
    public static final Techniques IN_RIGHT_SLIDE = Techniques.SlideInRight; //Using SlideOutUp in conjunction with SlideInUp would look kinda cool...
    public static final Techniques IN_LEFT_SLIDE = Techniques.SlideInLeft; //Using SlideOutUp in conjunction with SlideInUp would look kinda cool...
    public static final Techniques IN_SLIDE = Techniques.SlideInUp; //Using SlideOutUp in conjunction with SlideInUp would look kinda cool...
    public static final Techniques IN_FADE_DOWN = Techniques.FadeInDown; //Simple fade in and down animation
    public static final Techniques IN_FADE_UP = Techniques.FadeInUp; //Simple fade in and up animation
    public static final Techniques IN_DROP = Techniques.DropOut; //Looks cool, falls down from top and bounces
    public static final Techniques IN_TADA = Techniques.Tada; //Fun one, seems useful for focusing on a view
    public static final Techniques OUT_ROLL = Techniques.RollOut;
    public static final Techniques OUT_ZOOM = Techniques.ZoomOut;
    public static final Techniques IN_FLASH = Techniques.Flash; //Quick flash

    */

    //////////////////////
    //Misc Useful Values//
    //////////////////////

    /**
     * List of States for dropdown menus or other GUI-related uses
     */
    public static final String[] ALL_US_STATES = {"California", "Alabama", "Arkansas", "Arizona", "Alaska",
            "Colorado", "Connecticut", "Delaware", "Florida", "Georgia", "Hawaii", "Idaho", "Illinois",
            "Indiana", "Iowa", "Kansas", "Kentucky", "Louisiana", "Maine", "Maryland", "Massachusetts",
            "Michigan", "Minnesota", "Mississippi", "Missouri", "Montana", "Nebraska", "Nevada", "New Hampshire",
            "New Jersey", "New Mexico", "New York", "North Carolina", "North Dakota", "Ohio", "Oklahoma", "Oregon",
            "Pennsylvania", "Rhode Island", "South Carolina", "South Dakota", "Tennessee", "Texas", "Utah", "Vermont",
            "Virginia", "Washington", "Washington DC", "West Virginia", "Wisconsin", "Wyoming"
    };

    /**
     * USA Territories. List obtained from:
     *   https://www.50states.com/abbreviations.htm
     */
    public static enum USATerritories {
        Alabama("Alabama", "AL"),
        Alaska("Alaska", "AK"),
        Arizona("Arizona", "AZ"),
        Arkansas("Arkansas", "AR"),
        California("California", "CA"),
        Colorado("Colorado", "CO"),
        Connecticut("Connecticut", "CT"),
        Delaware("Delaware", "DE"),
        Florida("Florida", "FL"),
        Georgia("Georgia", "GA"),
        Hawaii("Hawaii", "HI"),
        Idaho("Idaho", "ID"),
        Illinois("Illinois", "IL"),
        Indiana("Indiana", "IN"),
        Iowa("Iowa", "IA"),
        Kansas("Kansas", "KS"),
        Kentucky("Kentucky", "KY"),

Answer: Louisiana("Louisiana", "LA"),

<think>
The enum USATerritories lists US states with name and abbreviation. After the Kentucky entry, the next state alphabetically is Louisiana. Enum constants continue separated by commas, so the next line should define Louisiana.
</think>
Louisiana("Louisiana", "LA"),


Context:
"""
Code generator script to make the Cython BLAS and LAPACK wrappers
from the files "cython_blas_signatures.txt" and
"cython_lapack_signatures.txt" which contain the signatures for
all the BLAS/LAPACK routines that should be included in the wrappers.
"""

from collections import defaultdict
from operator import itemgetter
import os

BASE_DIR = os.path.abspath(os.path.dirname(__file__))

fortran_types = {'int': 'integer',
                 'c': 'complex',
                 'd': 'double precision',
                 's': 'real',
                 'z': 'complex*16',
                 'char': 'character',
                 'bint': 'logical'}

c_types = {'int': 'int',
           'c': 'npy_complex64',
           'd': 'double',
           's': 'float',
           'z': 'npy_complex128',
           'char': 'char',
           'bint': 'int',
           'cselect1': '_cselect1',
           'cselect2': '_cselect2',
           'dselect2': '_dselect2',
           'dselect3': '_dselect3',
           'sselect2': '_sselect2',
           'sselect3': '_sselect3',
           'zselect1': '_zselect1',
           'zselect2': '_zselect2'}

def arg_names_and_types(args):
    return zip(*[arg.split(' *') for arg in args.split(', ')])

pyx_func_template = """
cdef extern from "{header_name}":
    void _fortran_{name} "F_FUNC({name}wrp, {upname}WRP)"({ret_type} *out, {fort_args}) nogil
cdef {ret_type} {name}({args}) nogil:
    cdef {ret_type} out
    _fortran_{name}(&out, {argnames})
    return out
"""

npy_types = {'c': 'npy_complex64', 'z': 'npy_complex128',
             'cselect1': '_cselect1', 'cselect2': '_cselect2',
             'dselect2': '_dselect2', 'dselect3': '_dselect3',
             'sselect2': '_sselect2', 'sselect3': '_sselect3',
             'zselect1': '_zselect1', 'zselect2': '_zselect2'}

def arg_casts(arg):
    if arg in ['npy_complex64', 'npy_complex128', '_cselect1', '_cselect2',
               '_dselect2', '_dselect3', '_sselect2', '_sselect3',
               '_zselect1', '_zselect2']:
        return '<{0}*>'.format(arg)
    return ''

def pyx_decl_func(name, ret_type, args, header_name):
    argtypes, argnames = arg_names_and_types(args)
    # Fix the case where one of the arguments has the same name as the
    # abbreviation for the argument type.
    # Otherwise the variable passed as an argument is considered overwrites
    # the previous typedef and Cython compilation fails.
    if ret_type in argnames:
        argnames = [n if n != ret_type else ret_type + '_' for n in argnames]
        argnames = [n if n not in ['lambda', 'in'] else n + '_'
                    for n in argnames]
        args = ', '.join([' *'.join([n, t])
                          for n, t in zip(argtypes, argnames)])
    argtypes = [npy_types.get(t, t) for t in argtypes]
    fort_args = ', '.join([' *'.join([n, t])
                           for n, t in zip(argtypes, argnames)])
    argnames = [arg_casts(t) + n for n, t in zip(argnames, argtypes)]
    argnames = ', '.join(argnames)
    c_ret_type = c_types[ret_type]
    args = args.replace('lambda', 'lambda_')
    return pyx_func_template.format(name=name, upname=name.upper(), args=args,
                                    fort_args=fort_args, ret_type=ret_type,
                                    c_ret_type=c_ret_type, argnames=argnames,
                                    header_name=header_name)

pyx_sub_template = """cdef extern from "{header_name}":
    void _fortran_{name} "F_FUNC({name},{upname})"({fort_args}) nogil
cdef void {name}({args}) nogil:
    _fortran_{name}({argnames})
"""

def pyx_decl_sub(name, args, header_name):
    argtypes, argnames = arg_names_and_types(args)
    argtypes = [npy_types.get(t, t) for t in argtypes]
    argnames = [n if n not in ['lambda', 'in'] else n + '_' for n in argnames]
    fort_args = ', '.join([' *'.join([n, t])
                           for n, t in zip(argtypes, argnames)])
    argnames = [arg_casts(t) + n for n, t in zip(argnames, argtypes)]
    argnames = ', '.join(argnames)
    args = args.replace('*lambda,', '*lambda_,').replace('*in,', '*in_,')
    return pyx_sub_template.format(name=name, upname=name.upper(),
                                   args=args, fort_args=fort_args,
                                   argnames=argnames, header_name=header_name)

blas_pyx_preamble = '''# cython: boundscheck = False
# cython: wraparound = False
# cython: cdivision = True

"""
BLAS Functions for Cython
=========================

Usable from Cython via::

    cimport scipy.linalg.cython_blas

These wrappers do not check for alignment of arrays.
Alignment should be checked before these wrappers are used.

Raw function pointers (Fortran-style pointer arguments):

- {}

"""

# Within SciPy, these wrappers can be used via relative or absolute cimport.
# Examples:
# from ..linalg cimport cython_blas
# from scipy.linalg cimport cython_blas
# cimport scipy.linalg.cython_blas as cython_blas
# cimport ..linalg.cython_blas as cython_blas

# Within SciPy, if BLAS functions are needed in C/C++/Fortran,
# these wrappers should not be used.
# The original libraries should be linked directly.

cdef extern from "fortran_defs.h":
    pass

from numpy cimport npy_complex64, npy_complex128

'''

def make_blas_pyx_preamble(all_sigs):
    names = [sig[0] for sig in all_sigs]
    return blas_pyx_preamble.format("\n- ".join(names))

lapack_pyx_preamble = '''"""
LAPACK functions for Cython
===========================

Usable from Cython via::

    cimport scipy.linalg.cython_lapack

This module provides Cython-level wrappers for all primary routines included
in LAPACK 3.4.0 except for ``zcgesv`` since its interface is not consistent
from LAPACK 3.4.0 to 3.6.0. It also provides some of the
fixed-api auxiliary routines.

These wrappers do not check for alignment of arrays.
Alignment should be checked before these wrappers are used.

Raw function pointers (Fortran-style pointer arguments):

- {}

"""

# Within SciPy, these wrappers can be used via relative or absolute cimport.
# Examples:
# from ..linalg cimport cython_lapack
# from scipy.linalg cimport cython_lapack
# cimport scipy.linalg.cython_lapack as cython_lapack
# cimport ..linalg.cython_lapack as cython_lapack

# Within SciPy, if LAPACK functions are needed in C/C++/Fortran,
# these wrappers should not be used.
# The original libraries should be linked directly.

cdef extern from "fortran_defs.h":
    pass

from numpy cimport npy_complex64, npy_complex128

cdef extern from "_lapack_subroutines.h":
    # Function pointer type declarations for
    # gees and gges families of functions.
    ctypedef bint _cselect1(npy_complex64*)
    ctypedef bint _cselect2(npy_complex64*, npy_complex64*)
    ctypedef bint _dselect2(d*, d*)
    ctypedef bint _dselect3(d*, d*, d*)
    ctypedef bint _sselect2(s*, s*)
    ctypedef bint _sselect3(s*, s*, s*)
    ctypedef bint _zselect1(npy_complex128*)
    ctypedef bint _zselect2(npy_complex128*, npy_complex128*)

'''

def make_lapack_pyx_preamble(all_sigs):
    names = [sig[0] for sig in all_sigs]
    return lapack_pyx_preamble.format("\n- ".join(names))

blas_py_wrappers = """

# Python-accessible wrappers for testing:

cdef inline bint _is_contiguous(double[:,:] a, int axis) nogil:
    return (a.strides[axis] == sizeof(a[0,0]) or a.shape[axis] == 1)

cpdef float complex _test_cdotc(float complex[:] cx, float complex[:] cy) nogil:
    cdef:
        int n = cx.shape[0]
        int incx = cx.strides[0] // sizeof(cx[0])
        int incy = cy.strides[0] // sizeof(cy[0])
    return cdotc(&n, &cx[0], &incx, &cy[0], &incy)

cpdef float complex _test_cdotu(float complex[:] cx, float complex[:] cy) nogil:
    cdef:
        int n = cx.shape[0]
        int incx = cx.strides[0] // sizeof(cx[0])
        int incy = cy.strides[0] // sizeof(cy[0])
    return cdotu(&n, &cx[0], &incx, &cy[0], &incy)

cpdef double _test_dasum(double[:] dx) nogil:
    cdef:
        int n = dx.shape[0]
        int incx = dx.strides[0] // sizeof(dx[0])
    return dasum(&n, &dx[0], &incx)

cpdef double _test_ddot(double[:] dx, double[:] dy) nogil:
    cdef:
        int n = dx.shape[0]
        int incx = dx.strides[0] // sizeof(dx[0])
        int incy = dy.strides[0] // sizeof(dy[0])
    return ddot(&n, &dx[0], &incx, &dy[0], &incy)

cpdef int _test_dgemm(double alpha, double[:,:] a, double[:,:] b, double beta,
                double[:,:] c) nogil except -1:
    cdef:
        char *transa
        char *transb
        int m, n, k, lda, ldb, ldc
        double *a0=&a[0,0]
        double *b0=&b[0,0]
        double *c0=&c[0,0]
    # In the case that c is C contiguous, swap a and b and
    # swap whether or not each of them is transposed.
    # This can be done because a.dot(b) = b.T.dot(a.T).T.
    if _is_contiguous(c, 1):
        if _is_contiguous(a, 1):
            transb = 'n'
            ldb = (&a[1,0]) - a0 if a.shape[0] > 1 else 1
        elif _is_contiguous(a, 0):
            transb = 't'
            ldb = (&a[0,1]) - a0 if a.shape[1] > 1 else 1
        else:
            with gil:
                raise ValueError("Input 'a' is neither C nor Fortran contiguous.")
        if _is_contiguous(b, 1):
            transa = 'n'
            lda = (&b[1,0]) - b0 if b.shape[0] > 1 else 1
        elif _is_contiguous(b, 0):
            transa = 't'
            lda = (&b[0,1]) - b0 if b.shape[1] > 1 else 1
        else:
            with gil:
                raise ValueError("Input 'b' is neither C nor Fortran contiguous.")
        k = b.shape[0]
        if k != a.shape[1]:
            with gil:
                raise ValueError("Shape mismatch in input arrays.")
        m = b.shape[1]
        n = a.shape[0]
        if n != c.shape[0] or m != c.shape[1]:
            with gil:
                raise ValueError("Output array does not have the correct shape.")
        ldc = (&c[1,0]) - c0 if c.shape[0] > 1 else 1
        dgemm(transa, transb, &m, &n, &k, &alpha, b0, &lda, a0,
                   &ldb, &beta, c0, &ldc)
    elif _is_contiguous(c, 0):
        if _is_contiguous(a, 1):
            transa = 't'
            lda = (&a[1,0]) - a0 if a.shape[0] > 1 else 1
        elif _is_contiguous(a, 0):
            transa = 'n'
            lda = (&a[0,1]) - a0 if a.shape[1] > 1 else 1
        else:
            with gil:
                raise ValueError("Input 'a' is neither C nor Fortran contiguous.")
        if _is_contiguous(b, 1):
            transb = 't'
            ldb = (&b[1,0]) - b0 if b.shape[0] > 1 else 1
        elif _is_contiguous(b, 0):
            transb = 'n'
            ldb = (&b[0,1]) - b0 if b.shape[1] > 1 else 1
        else:
            with gil:
                raise ValueError("Input 'b' is neither C nor Fortran contiguous.")
        m = a.shape[0]
        k = a.shape[1]
        if k != b.shape[0]:
            with gil:
                raise ValueError("Shape mismatch in input arrays.")
        n = b.shape[1]
        if m != c.shape[0] or n != c.shape[1]:
            with gil:
                raise ValueError("Output array does not have the correct shape.")
        ldc = (&c[0,1]) - c0 if c.shape[1] > 1 else 1
        dgemm(transa, transb, &m, &n, &k, &alpha, a0, &lda, b0,
                   &ldb, &beta, c0, &ldc)
    else:
        with gil:
            raise ValueError("Input 'c' is neither C nor Fortran contiguous.")
    return 0

cpdef double _test_dnrm2(double[:] x) nogil:
    cdef:
        int n = x.shape[0]
        int incx = x.strides[0] // sizeof(x[0])
    return dnrm2(&n, &x[0], &incx)

cpdef double _test_dzasum(double complex[:] zx) nogil:
    cdef:
        int n = zx.shape[0]
        int incx = zx.strides[0] // sizeof(zx[0])
    return dzasum(&n, &zx[0], &incx)

cpdef double _test_dznrm2(double complex[:] x) nogil:
    cdef:
        int n = x.shape[0]
        int incx = x.strides[0] // sizeof(x[0])
    return dznrm2(&n, &x[0], &incx)

cpdef int _test_icamax(float complex[:] cx) nogil:
    cdef:
        int n = cx.shape[0]
        int incx = cx.strides[0] // sizeof(cx[0])
    return icamax(&n, &cx[0], &incx)

cpdef int _test_idamax(double[:] dx) nogil:
    cdef:
        int n = dx.shape[0]
        int incx = dx.strides[0] // sizeof(dx[0])
    return idamax(&n, &dx[0], &incx)

cpdef int _test_isamax(float[:] sx) nogil:
    cdef:
        int n = sx.shape[0]
        int incx = sx.strides[0] // sizeof(sx[0])
    return isamax(&n, &sx[0], &incx)

cpdef int _test_izamax(double complex[:] zx) nogil:
    cdef:
        int n = zx.shape[0]
        int incx = zx.strides[0] // sizeof(zx[0])
    return izamax(&n, &zx[0], &incx)

cpdef float _test_sasum(float[:] sx) nogil:
    cdef:
        int n = sx.shape[0]
        int incx = sx.shape[0] // sizeof(sx[0])
    return sasum(&n, &sx[0], &incx)

cpdef float _test_scasum(float complex[:] cx) nogil:
    cdef:
        int n = cx.shape[0]
        int incx = cx.strides[0] // sizeof(cx[0])
    return scasum(&n, &cx[0], &incx)

cpdef float _test_scnrm2(float complex[:] x) nogil:
    cdef:
        int n = x.shape[0]
        int incx = x.strides[0] // sizeof(x[0])
    return scnrm2(&n, &x[0], &incx)

cpdef float _test_sdot(float[:] sx, float[:] sy) nogil:
    cdef:
        int n = sx.shape[0]
        int incx = sx.strides[0] // sizeof(sx[0])
        int incy = sy.strides[0] // sizeof(sy[0])
    return sdot(&n, &sx[0], &incx, &sy[0], &incy)

cpdef float _test_snrm2(float[:] x) nogil:
    cdef:
        int n = x.shape[0]
        int incx = x.shape[0] // sizeof(x[0])
    return snrm2(&n, &x[0], &incx)

cpdef double complex _test_zdotc(double complex[:] zx, double complex[:] zy) nogil:
    cdef:
        int n = zx.shape[0]
        int incx = zx.strides[0] // sizeof(zx[0])
        int incy = zy.strides[0] // sizeof(zy[0])
    return zdotc(&n, &zx[0], &incx, &zy[0], &incy)

cpdef double complex _test_zdotu(double complex[:] zx, double complex[:] zy) nogil:
    cdef:
        int n = zx.shape[0]
        int incx = zx.strides[0] // sizeof(zx[0])
        int incy = zy.strides[0] // sizeof(zy[0])
    return zdotu(&n, &zx[0], &incx, &zy[0], &incy)
"""

def generate_blas_pyx(func_sigs, sub_sigs, all_sigs, header_name):
    funcs = "\n".join(pyx_decl_func(*(s+(header_name,))) for s in func_sigs)
    subs = "\n" + "\n".join(pyx_decl_sub(*(s[::2]+(header_name,)))
                            for s in sub_sigs)
    return make_blas_pyx_preamble(all_sigs) + funcs + subs + blas_py_wrappers

lapack_py_wrappers = """

# Python accessible wrappers for testing:

def _test_dlamch(cmach):
    # This conversion is necessary to handle Python 3 strings.
    cmach_bytes = bytes(cmach)
    # Now that it is a bytes representation, a non-temporary variable
    # must be passed as a part of the function call.
    cdef char* cmach_char = cmach_bytes
    return dlamch(cmach_char)

def _test_slamch(cmach):
    # This conversion is necessary to handle Python 3 strings.
    cmach_bytes = bytes(cmach)
    # Now that it is a bytes representation, a non-temporary variable
    # must be passed as a part of the function call.
    cdef char* cmach_char = cmach_bytes
    return slamch(cmach_char)
"""

def generate_lapack_pyx(func_sigs, sub_sigs, all_sigs, header_name):
    funcs = "\n".join(pyx_decl_func(*(s+(header_name,))) for s in func_sigs)
    subs = "\n" + "\n".join(pyx_decl_sub(*(s[::2]+(header_name,)))
                            for s in sub_sigs)
    preamble = make_lapack_pyx_preamble(all_sigs)
    return preamble + funcs + subs + lapack_py_wrappers

pxd_template = """ctypedef {ret_type} {name}_t({args}) nogil
cdef {name}_t *{name}_f
"""
pxd_template = """cdef {ret_type} {name}({args}) nogil
"""

def pxd_decl(name, ret_type, args):
    args = args.replace('lambda', 'lambda_').replace('*in,', '*in_,')
    return pxd_template.format(name=name, ret_type=ret_type, args=args)

blas_pxd_preamble = """# Within scipy, these wrappers can be used via relative or absolute cimport.
# Examples:
# from ..linalg cimport cython_blas
# from scipy.linalg cimport cython_blas
# cimport scipy.linalg.cython_blas as cython_blas
# cimport ..linalg.cython_blas as cython_blas

# Within SciPy, if BLAS functions are needed in C/C++/Fortran,
# these wrappers should not be used.
# The original libraries should be linked directly.

ctypedef float s
ctypedef double d
ctypedef float complex c
ctypedef double complex z

"""

def generate_blas_pxd(all_sigs):
    body = '\n'.join(pxd_decl(*sig) for sig in all_sigs)
    return blas_pxd_preamble + body

lapack_pxd_preamble = """# Within SciPy, these wrappers can be used via relative or absolute cimport.
# Examples:
# from ..linalg cimport cython_lapack
# from scipy.linalg cimport cython_lapack
# cimport scipy.linalg.cython_lapack as cython_lapack
# cimport ..linalg.cython_lapack as cython_lapack

# Within SciPy, if LAPACK functions are needed in C/C++/Fortran,
# these wrappers should not be used.
# The original libraries should be linked directly.

ctypedef float s
ctypedef double d
ctypedef float complex c
ctypedef double complex z

# Function pointer type declarations for
# gees and gges families of functions.
ctypedef bint cselect1(c*)
ctypedef bint cselect2(c*, c*)
ctypedef bint dselect2(d*, d*)
ctypedef bint dselect3(d*, d*, d*)
ctypedef bint sselect2(s*, s*)
ctypedef bint sselect3(s*, s*, s*)
ctypedef bint zselect1(z*)
ctypedef bint zselect2(z*, z*)

"""

def generate_lapack_pxd(all_sigs):
    return lapack_pxd_preamble + '\n'.join(pxd_decl(*sig) for sig in all_sigs)

fortran_template = """      subroutine {name}wrp(
     +    ret,
     +    {argnames}
     +    )
        external {wrapper}
        {ret_type} {wrapper}
        {ret_type} ret
        {argdecls}
        ret = {wrapper}(
     +    {argnames}
     +    )
      end
"""

dims = {'work': '(*)', 'ab': '(ldab,*)', 'a': '(lda,*)', 'dl': '(*)',
        'd': '(*)', 'du': '(*)', 'ap': '(*)', 'e': '(*)', 'lld': '(*)'}

xy_specialized_dims = {'x': '', 'y': ''}
a_specialized_dims = {'a': '(*)'}
special_cases = defaultdict(dict,
                            ladiv = xy_specialized_dims,
                            lanhf = a_specialized_dims,
                            lansf = a_specialized_dims,
                            lapy2 = xy_specialized_dims,
                            lapy3 = xy_specialized_dims)

def process_fortran_name(name, funcname):
    if 'inc' in name:
        return name
    special = special_cases[funcname[1:]]
    if 'x' in name or 'y' in name:
        suffix = special.get(name, '(n)')
    else:
        suffix = special.get(name, '')
    return name + suffix

def called_name(name):
    included = ['cdotc', 'cdotu', 'zdotc', 'zdotu', 'cladiv', 'zladiv']
    if name in included:
        return "w" + name
    return name

def fort_subroutine_wrapper(name, ret_type, args):
    wrapper = called_name(name)
    types, names = arg_names_and_types(args)
    argnames = ',\n     +    '.join(names)

    names = [process_fortran_name(n, name) for n in names]
    argdecls = '\n        '.join('{0} {1}'.format(fortran_types[t], n)
                                 for n, t in zip(names, types))
    return fortran_template.format(name=name, wrapper=wrapper,
                                   argnames=argnames, argdecls=argdecls,
                                   ret_type=fortran_types[ret_type])

def generate_fortran(func_sigs):
    return "\n".join(fort_subroutine_wrapper(*sig) for sig in func_sigs)

def make_c_args(args):

Answer: types, names = arg_names_and_types(args)

<think>
The function make_c_args is meant to process a string of argument specifications. The first step is to split the string into types and names, just like other helper functions in the script (e.g., pyx_decl_func and fort_subroutine_wrapper). Therefore the next line should call arg_names_and_types to obtain the separate lists.
</think>
argtypes, argnames = arg_names_and_types(args)