예제 #1
0
파일: Program.cs 프로젝트: Frassle/Ibasa
        static void Main(string[] args)
        {
            string root = System.IO.Path.Combine("..", "..", "..", "Numerics");

            var integer_path = System.IO.Path.Combine(root, "Integer.cs");
            System.IO.File.Delete(integer_path);
            foreach (var size in Integer.Sizes)
            {
                var integer = new Integer(size, true);
                integer.Generate();

                System.IO.File.AppendAllText(integer_path, integer.Text);
                Console.WriteLine("Done - " + integer.Name);

                var uinteger = new Integer(size, false);
                uinteger.Generate();

                System.IO.File.AppendAllText(integer_path, uinteger.Text);
                Console.WriteLine("Done - " + uinteger.Name);
            }

            foreach (var type in Color.Types)
            {
                var color = new Color(type);
                color.Generate();

                var path = System.IO.Path.Combine(root, color.Name + ".cs");
                System.IO.File.WriteAllText(path, color.Text);
                Console.WriteLine("Done - " + color.Name);
            }

            foreach (var type in Quaternion.Types)
            {
                var quaternion = new Quaternion(type);
                quaternion.Generate();

                var path = System.IO.Path.Combine(root, "Geometry", quaternion.Name + ".cs");
                System.IO.File.WriteAllText(path, quaternion.Text);
                Console.WriteLine("Done - " + quaternion.Name);
            } 
            
            foreach (var type in Plane.Types)
            {
                var plane = new Plane(type);
                plane.Generate();

                var path = System.IO.Path.Combine(root, "Geometry", plane.Name + ".cs");
                System.IO.File.WriteAllText(path, plane.Text);
                Console.WriteLine("Done - " + plane.Name);
            }

            foreach (int dimension in Vector.Sizes)
            {
                foreach (var type in Vector.Types)
                {
                    var vector = new Vector(type, dimension);
                    vector.Generate();

                    var path = System.IO.Path.Combine(root, "Vectors", vector.Name + ".cs");
                    System.IO.File.WriteAllText(path, vector.Text);
                    Console.WriteLine("Done - " + vector.Name);
                }
            }

            foreach (int rows in Matrix.Sizes)
            {
                foreach (int columns in Matrix.Sizes)
                {
                    foreach (var type in Matrix.Types)
                    {
                        var matrix = new Matrix(type, rows, columns);
                        matrix.Generate();
                        var path = System.IO.Path.Combine(root, "Matrices", matrix.Name + ".cs");
                        System.IO.File.WriteAllText(path, matrix.Text);
                        Console.WriteLine("Done - " + matrix.Name);
                    }
                }
            }

            foreach (var type in Shapes.Types)
            {
                var rpath = System.IO.Path.Combine(root, "Geometry");

                var line1 = new Line(type, 1);
                line1.Generate();
                System.IO.File.WriteAllText(System.IO.Path.Combine(rpath, line1.Name + ".cs"), line1.Text);
                Console.WriteLine("Done - " + line1.Name);

                foreach (int dimension in Shapes.Sizes)
                {
                    var point = new Point(type, dimension);
                    point.Generate();
                    System.IO.File.WriteAllText(System.IO.Path.Combine(rpath, point.Name + ".cs"), point.Text);
                    Console.WriteLine("Done - " + point.Name);

                    var size = new Size(type, dimension);
                    size.Generate();
                    System.IO.File.WriteAllText(System.IO.Path.Combine(rpath, size.Name + ".cs"), size.Text);
                    Console.WriteLine("Done - " + size.Name);

                    var polygon = new Polygon(type, dimension);
                    polygon.Generate();
                    System.IO.File.WriteAllText(System.IO.Path.Combine(rpath, polygon.Name + ".cs"), polygon.Text);
                    Console.WriteLine("Done - " + polygon.Name);

                    var line = new Line(type, dimension);
                    line.Generate();
                    System.IO.File.WriteAllText(System.IO.Path.Combine(rpath, line.Name + ".cs"), line.Text);
                    Console.WriteLine("Done - " + line.Name);
                }

                var rectangle = new Rectangle(type);
                rectangle.Generate();
                System.IO.File.WriteAllText(System.IO.Path.Combine(rpath, rectangle.Name + ".cs"), rectangle.Text);
                Console.WriteLine("Done - " + rectangle.Name);

                var box = new Box(type);
                box.Generate();
                System.IO.File.WriteAllText(System.IO.Path.Combine(rpath, box.Name + ".cs"), box.Text);
                Console.WriteLine("Done - " + box.Name);

                var ellipse = new Ellipse(type);
                ellipse.Generate();
                System.IO.File.WriteAllText(System.IO.Path.Combine(rpath, ellipse.Name + ".cs"), ellipse.Text);
                Console.WriteLine("Done - " + ellipse.Name);

                var circle = new Circle(type);
                circle.Generate();
                System.IO.File.WriteAllText(System.IO.Path.Combine(rpath, circle.Name + ".cs"), circle.Text);
                Console.WriteLine("Done - " + circle.Name);

                var sphere = new Sphere(type);
                sphere.Generate();
                System.IO.File.WriteAllText(System.IO.Path.Combine(rpath, sphere.Name + ".cs"), sphere.Text);
                Console.WriteLine("Done - " + sphere.Name);
            }

            foreach (var type in Ray.Types)
            {
                var ray = new Ray(type);
                ray.Generate();

                var path = System.IO.Path.Combine(root, "Geometry", ray.Name + ".cs");
                System.IO.File.WriteAllText(path, ray.Text);
                Console.WriteLine("Done - " + ray.Name);
            }
        }
예제 #2
0
파일: Vector.cs 프로젝트: Frassle/Ibasa
        void Conversions()
        {
            WriteLine("#region Conversions");

            foreach (var type in Types.Where(t => t != Type))
            {
                string imex = type.IsImplicitlyConvertibleTo(Type) ? "implicit" : "explicit";

                Vector other = new Vector(type, Dimension);

                var casts = string.Join(", ",
                    Components.Select(component => string.Format("({0})value.{1}", Type, component)));
                
                WriteLine("/// <summary>");
                WriteLine("/// Defines an {0} conversion of a {1} value to a {2}.", imex, other, Name);
                WriteLine("/// </summary>");
                WriteLine("/// <param name=\"value\">The value to convert to a {0}.</param>", Name);
                WriteLine("/// <returns>A {0} that has all components equal to value.</returns>", Name); 
                if (Type.IsCLSCompliant && !type.IsCLSCompliant)
                {
                    WriteLine("[CLSCompliant(false)]");
                }
                WriteLine("public static {0} operator {1}({2} value)", imex, Name, other);
                WriteLine("{");
                Indent();
                WriteLine("return new {0}({1});", Name, casts);
                Dedent();
                WriteLine("}");
            }

            WriteLine("#endregion");
        }
예제 #3
0
파일: Vector.cs 프로젝트: Frassle/Ibasa
        void Functions()
        {
            WriteLine("/// <summary>");
            WriteLine("/// Provides static methods for vector functions.");
            WriteLine("/// </summary>");
            WriteLine("public static partial class Vector");
            WriteLine("{");
            Indent();

            var result = new Vector(Type.PositiveType, Dimension);

            #region Binary
            WriteLine("#region Binary");
            WriteLine("/// <summary>");
            WriteLine("/// Writes the given <see cref=\"{0}\"/> to an <see cref=\"Ibasa.IO.BinaryWriter\">.", Name);
            WriteLine("/// </summary>");
            WriteLine("public static void Write(this Ibasa.IO.BinaryWriter writer, {0} vector)", Name);
            WriteLine("{");
            Indent();
            for (int i = 0; i < Dimension; ++i)
            {
                WriteLine("writer.Write(vector.{0});", Components[i]);
            }
            Dedent();
            WriteLine("}");
            WriteLine("/// <summary>");
            WriteLine("/// Reads a <see cref=\"{0}\"/> from an <see cref=\"Ibasa.IO.BinaryReader\">.", Name);
            WriteLine("/// </summary>");
            WriteLine("public static {0} Read{0}(this Ibasa.IO.BinaryReader reader)", Name);
            WriteLine("{");
            Indent();
            WriteLine("return new {0}({1});", Name, string.Join(", ", Components.Select(c => string.Format("reader.Read{0}()", Type.CLRName))));
            Dedent();
            WriteLine("}");
            WriteLine("#endregion");
            #endregion

            #region Pack
            if(!Type.IsReal)
            {
                WriteLine("#region Pack");

                int size = Components.Length * Type.Size;

                var packed = NumberType.Types.
                    Where(type => !type.IsReal && (type.IsCLSCompliant || !Type.IsCLSCompliant) && type.Size >= size).
                    Concat(new NumberType[] { NumberType.Long }).
                    OrderBy(type => type.Size).
                    First();

                var args = Components.Select(c => string.Format("{0}Bits", c.Name.ToLower())).ToArray();
                int bits = packed.Size * 8;

                WriteLine("public static {0} Pack({1}, {2} vector)", packed, 
                    string.Join(", ", args.Select(arg => string.Format("int {0}", arg))), Name);
                WriteLine("{");
                Indent();
                for (int i = 0; i < args.Length; ++i)
                {
                    WriteLine("Contract.Requires(0 <= {0} && {0} <= {1}, \"{0} must be between 0 and {1} inclusive.\");", 
                        args[i], Type.Size * 8);
                }
                WriteLine("Contract.Requires({0} <= {1});", string.Join(" + ", args), bits);

                for (int i = 0; i < Components.Length; ++i)
                {
                    var var = Components[i].Name.ToLower();
                    var name = Components[i].Name;
                    var bitarg = args[i];
                    var offset = string.Join(" + ", Enumerable.Range(0, i).Select(j => args[j]));
                    WriteLine("ulong {0} = (ulong)(vector.{1}) >> ({2} - {3});", var, name, bits, bitarg);
                    if (offset.Length != 0)
                    {
                        WriteLine("{0} <<= {1};", var, offset);
                    }
                }

                WriteLine("return ({0})({1});", packed, string.Join(" | ", Components.Select(component => component.Name.ToLower())));
                Dedent(); 
                WriteLine("}");

                if (packed.Size >= size)
                {
                    WriteLine("public static {0} Pack({1} vector)", packed, Name);
                    WriteLine("{");
                    Indent();
                    for (int i = 0; i < Components.Length; ++i)
                    {
                        var var = Components[i].Name.ToLower();
                        var name = Components[i].Name;
                        var offset = (Type.Size * 8 * i).ToString();
                        WriteLine("ulong {0} = (ulong)(vector.{1}) << {2};", var, name, offset);
                    }

                    WriteLine("return ({0})({1});", packed, string.Join(" | ", Components.Select(component => component.Name.ToLower())));
                    Dedent();
                    WriteLine("}");
                }

                // Unpack

                WriteLine("public static {0} Unpack({1}, {2} bits)", Name,
                    string.Join(", ", args.Select(arg => string.Format("int {0}", arg))), Type);
                WriteLine("{");
                Indent();
                for (int i = 0; i < args.Length; ++i)
                {
                    WriteLine("Contract.Requires(0 <= {0} && {0} <= {1}, \"{0} must be between 0 and {1} inclusive.\");",
                        args[i], Type.Size * 8);
                }
                WriteLine("Contract.Requires({0} <= {1});", string.Join(" + ", args), bits);

                for (int i = 0; i < Components.Length; ++i)
                {
                    var var = Components[i].Name.ToLower();
                    var name = Components[i].Name;
                    var bitarg = args[i];
                    var offset = string.Join(" + ", Enumerable.Range(0, i).Select(j => args[j]));
                    if (offset != "")
                    {
                        WriteLine("ulong {0} = (ulong)(bits) >> ({1});", var, offset);
                    }
                    else
                    {
                        WriteLine("ulong {0} = (ulong)(bits);", var);
                    }
                    WriteLine("{0} &= ((1UL << {1}) - 1);", var, bitarg);
                }

                WriteLine("return new {0}({1});", Name,
                    string.Join(", ", Components.Select(component => string.Format("({0}){1}", Type, component.Name.ToLower()))));
                Dedent();
                WriteLine("}");
                
                WriteLine("#endregion");
            }
            #endregion

            #region Operations
            WriteLine("#region Operations");
            if (Type.NegativeType != NumberType.Invalid)
            {
                var negVector = new Vector(Type.NegativeType, Dimension);

                WriteLine("/// <summary>");
                WriteLine("/// Returns the additive inverse of a vector.");
                WriteLine("/// </summary>");
                WriteLine("/// <param name=\"value\">A vector.</param>");
                WriteLine("/// <returns>The negative of value.</returns>");
                WriteLine("public static {0} Negative({1} value)", negVector, Name);
                WriteLine("{");
                Indent();
                WriteLine("return new {0}({1});", negVector,
                    string.Join(", ", Components.Select(component => "-value." + component)));
                Dedent();
                WriteLine("}");
            }

            WriteLine("/// <summary>");
            WriteLine("/// Adds two vectors and returns the result.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"left\">The first value to add.</param>");
            WriteLine("/// <param name=\"right\">The second value to add.</param>");
            WriteLine("/// <returns>The sum of left and right.</returns>");
            WriteLine("public static {0} Add({1} left, {1} right)", result, Name);
            WriteLine("{");
            Indent();
            WriteLine("return new {0}({1});", result,
                string.Join(", ", Components.Select(component => string.Format("left.{0} + right.{0}", component))));
            Dedent();
            WriteLine("}");

            WriteLine("/// <summary>");
            WriteLine("/// Subtracts one vectors from another and returns the result.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"left\">The value to subtract from (the minuend).</param>");
            WriteLine("/// <param name=\"right\">The value to subtract (the subtrahend).</param>");
            WriteLine("/// <returns>The result of subtracting right from left (the difference).</returns>");
            WriteLine("public static {0} Subtract({1} left, {1} right)", result, Name);
            WriteLine("{");
            Indent();
            WriteLine("return new {0}({1});", result,
                string.Join(", ", Components.Select(component => string.Format("left.{0} - right.{0}", component))));
            Dedent();
            WriteLine("}");

            WriteLine("/// <summary>");
            WriteLine("/// Returns the product of a vector and scalar.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"vector\">The vector to multiply.</param>");
            WriteLine("/// <param name=\"scalar\">The scalar to multiply.</param>");
            WriteLine("/// <returns>The product of the left and right parameters.</returns>");
            WriteLine("public static {0} Multiply({1} vector, {2} scalar)", result, Name, result.Type);
            WriteLine("{");
            Indent();
            WriteLine("return new {0}({1});", result,
                string.Join(", ", Components.Select(component => string.Format("vector.{0} * scalar", component))));
            Dedent();
            WriteLine("}");

            if (Dimension <= 4 && Matrix.Types.Contains(Type))
            {
                foreach (var size in Matrix.Sizes)
                {
                    var matrix = new Matrix(Type, size, Dimension);
                    var vector = new Vector(Type, size);

                    WriteLine("/// <summary>");
                    WriteLine("/// Returns the product of a matrix and vector.");
                    WriteLine("/// </summary>");
                    WriteLine("/// <param name=\"matrix\">The matrix to multiply.</param>");
                    WriteLine("/// <param name=\"vector\">The vector to multiply.</param>");
                    WriteLine("/// <returns>The product of the left and right parameters.</returns>");
                    WriteLine("public static {0} Multiply({1} matrix, {2} vector)", vector, matrix, Name);
                    WriteLine("{");

                    Indent();
                    WriteLine("return new {0}({1});", vector, string.Join(", ",
                        vector.Components.Select(i =>
                        string.Join(" + ", Enumerable.Range(0, Dimension).Select(j =>
                            string.Format("matrix.M{0}{1} * vector.{2}", i.Index + 1, j + 1, Components[j]))))));
                    Dedent();
                    WriteLine("}");
                }
            }

            WriteLine("/// <summary>");
            WriteLine("/// Divides a vector by a scalar and returns the result.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"vector\">The vector to be divided (the dividend).</param>");
            WriteLine("/// <param name=\"scalar\">The scalar to divide by (the divisor).</param>");
            WriteLine("/// <returns>The result of dividing left by right (the quotient).</returns>");
            WriteLine("public static {0} Divide({1} vector, {2} scalar)", result, Name, result.Type);
            WriteLine("{");
            Indent();
            WriteLine("return new {0}({1});", result,
                string.Join(", ", Components.Select(component => string.Format("vector.{0} / scalar", component))));
            Dedent();
            WriteLine("}");
            WriteLine("#endregion");
            #endregion

            #region Equatable
            WriteLine("#region Equatable");
            WriteLine("/// <summary>");
            WriteLine("/// Returns a value that indicates whether two vectors are equal.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"left\">The first vector to compare.</param>");
            WriteLine("/// <param name=\"right\">The second vector to compare.</param>");
            WriteLine("/// <returns>true if the left and right are equal; otherwise, false.</returns>");
            WriteLine("public static bool Equals({0} left, {0} right)", Name);
            WriteLine("{");
            Indent();
            WriteLine("return left == right;");
            Dedent();
            WriteLine("}");
            WriteLine("#endregion");
            #endregion

            #region Products
            WriteLine("#region Products");            
            WriteLine("/// <summary>");
            WriteLine("/// Calculates the dot product (inner product) of two vectors.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"left\">First source vector.</param>");
            WriteLine("/// <param name=\"right\">Second source vector.</param>");
            WriteLine("/// <returns>The dot product of the two vectors.</returns>");
            if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
            WriteLine("public static {0} Dot({1} left, {1} right)", result.Type, Name);
            WriteLine("{");
            Indent();
            var dotproduct = string.Join(" + ", Components.Select(component => string.Format("left.{0} * right.{0}", component)));
            WriteLine("return {0};", dotproduct);
            Dedent();
            WriteLine("}");

            if (Dimension == 3 && Type.IsReal)
            {
                WriteLine("/// <summary>");
                WriteLine("/// Calculates the cross product (outer product) of two vectors.");
                WriteLine("/// </summary>");
                WriteLine("/// <param name=\"left\">First source vector.</param>");
                WriteLine("/// <param name=\"right\">Second source vector.</param>");
                WriteLine("/// <returns>The cross product of the two vectors.</returns>");
                if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
                WriteLine("public static {0} Cross({1} left, {1} right)", result, Name);
                WriteLine("{");
                Indent();
                WriteLine("return new {0}(", result);
                Indent();
                WriteLine("left.Y * right.Z - left.Z * right.Y,");
                WriteLine("left.Z * right.X - left.X * right.Z,");
                WriteLine("left.X * right.Y - left.Y * right.X);");
                Dedent();
                Dedent();
                WriteLine("}");
            }
            WriteLine("#endregion");      
            #endregion

            #region Test
            WriteLine("#region Test");
            WriteLine("/// <summary>");
            WriteLine("/// Determines whether all components of a vector are non-zero.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"value\">A vector.</param>");
            WriteLine("/// <returns>true if all components are non-zero; false otherwise.</returns>");
            if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
            WriteLine("public static bool All({0} value)", Name);
            WriteLine("{");
            Indent();
            WriteLine("return {0};",
                string.Join(" && ", Components.Select(component => string.Format("value.{0} != 0", component))));
            Dedent();
            WriteLine("}");
            WriteLine("/// <summary>");
            WriteLine("/// Determines whether all components of a vector satisfy a condition."); 
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"value\">A vector.</param>");
            WriteLine("/// <param name=\"predicate\">A function to test each component for a condition.</param>");
            WriteLine("/// <returns>true if every component of the vector passes the test in the specified");
            WriteLine("/// predicate; otherwise, false.</returns>");
            if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
            WriteLine("public static bool All({0} value, Predicate<{1}> predicate)", Name, Type);
            WriteLine("{");
            Indent();
            WriteLine("return {0};",
                string.Join(" && ", Components.Select(component => string.Format("predicate(value.{0})", component))));
            Dedent();
            WriteLine("}");
            WriteLine("/// <summary>");
            WriteLine("/// Determines whether any component of a vector is non-zero.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"value\">A vector.</param>");
            WriteLine("/// <returns>true if any components are non-zero; false otherwise.</returns>");
            if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
            WriteLine("public static bool Any({0} value)", Name);
            WriteLine("{");
            Indent();
            WriteLine("return {0};",
                string.Join(" || ", Components.Select(component => string.Format("value.{0} != 0", component))));
            Dedent();
            WriteLine("}");
            WriteLine("/// <summary>");
            WriteLine("/// Determines whether any components of a vector satisfy a condition.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"value\">A vector.</param>");
            WriteLine("/// <param name=\"predicate\">A function to test each component for a condition.</param>");
            WriteLine("/// <returns>true if any component of the vector passes the test in the specified");
            WriteLine("/// predicate; otherwise, false.</returns>");
            if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
            WriteLine("public static bool Any({0} value, Predicate<{1}> predicate)", Name, Type);
            WriteLine("{");
            Indent();
            WriteLine("return {0};",
                string.Join(" || ", Components.Select(component => string.Format("predicate(value.{0})", component))));
            Dedent();
            WriteLine("}");
            WriteLine("#endregion");
            #endregion

            #region Properties
            WriteLine("#region Properties");
            WriteLine("/// <summary>");
            WriteLine("/// Computes the absolute squared value of a vector and returns the result.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"value\">A vector.</param>");
            WriteLine("/// <returns>The absolute squared value of value.</returns> ");
            if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
            WriteLine("public static {0} AbsoluteSquared({1} value)", result.Type, Name);
            WriteLine("{");
            Indent();
            WriteLine("return Dot(value, value);");
            Dedent();
            WriteLine("}");
            WriteLine("/// <summary>");
            WriteLine("/// Computes the absolute value (or modulus or magnitude) of a vector and returns the result.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"value\">A vector.</param>");
            WriteLine("/// <returns>The absolute value of value.</returns>");
            if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
            WriteLine("public static {0} Absolute({1} value)", Type.RealType, Name);
            WriteLine("{");
            Indent();
            WriteLine("return Functions.Sqrt(AbsoluteSquared(value));");
            Dedent();
            WriteLine("}");
            var realVector = new Vector(Type.RealType, Dimension);
            WriteLine("/// <summary>");
            WriteLine("/// Computes the normalized value (or unit) of a vector.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"value\">A vector.</param>");
            WriteLine("/// <returns>The normalized value of value.</returns>");
            if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
            WriteLine("public static {0} Normalize({1} value)", realVector, Name);
            WriteLine("{");
            Indent();
            WriteLine("var absolute = Absolute(value);");
            WriteLine("if(absolute <= {0}.Epsilon)", Type.RealType);
            WriteLine("{");
            Indent();
            WriteLine("return {0}.Zero;", Name);
            Dedent();
            WriteLine("}");
            WriteLine("else");
            WriteLine("{");
            Indent();
            WriteLine("return ({0})value / absolute;", realVector);
            Dedent();
            WriteLine("}");
            Dedent();
            WriteLine("}");
            WriteLine("#endregion");
            #endregion

            #region Per component
            WriteLine("#region Per component");

            WriteLine("#region Map");
            foreach(var type in Types)
            {
                var map = new Vector(type, Dimension);

                WriteLine("/// <summary>");
                WriteLine("/// Maps the components of a vector and returns the result.");
                WriteLine("/// </summary>");
                WriteLine("/// <param name=\"value\">The vector to map.</param>");
                WriteLine("/// <param name=\"mapping\">A mapping function to apply to each component.</param>");
                WriteLine("/// <returns>The result of mapping each component of value.</returns>");
                if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
                WriteLine("public static {0} Map({1} value, Func<{2}, {3}> mapping)", map, Name, Type, map.Type);
                WriteLine("{");
                Indent();
                WriteLine("return new {0}({1});", map,
                    string.Join(", ", Components.Select(component => string.Format("mapping(value.{0})", component))));
                Dedent();
                WriteLine("}");
            }
            WriteLine("#endregion");

            WriteLine("/// <summary>");
            WriteLine("/// Multiplys the components of two vectors and returns the result.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"left\">The first vector to modulate.</param>");
            WriteLine("/// <param name=\"right\">The second vector to modulate.</param>");
            WriteLine("/// <returns>The result of multiplying each component of left by the matching component in right.</returns>");
            if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
            WriteLine("public static {0} Modulate({1} left, {1} right)", result, Name);
            WriteLine("{");
            Indent();
            WriteLine("return new {0}({1});", result, 
                string.Join(", ", Components.Select(component => string.Format("left.{0} * right.{0}", component))));
            Dedent();
            WriteLine("}");
            WriteLine("/// <summary>");
            WriteLine("/// Returns the absolute value (per component).");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"value\">A vector.</param>");
            WriteLine("/// <returns>The absolute value (per component) of value.</returns>");
            if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
            WriteLine("public static {0} Abs({0} value)", Name);
            WriteLine("{");
            Indent();
            WriteLine("return new {0}({1});", Name, 
                string.Join(", ", Components.Select(component => string.Format("Functions.Abs(value.{0})", component))));
            Dedent();
            WriteLine("}");
            WriteLine("/// <summary>");
            WriteLine("/// Returns a vector that contains the lowest value from each pair of components.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"value1\">The first vector.</param>");
            WriteLine("/// <param name=\"value2\">The second vector.</param>");
            WriteLine("/// <returns>The lowest of each component in left and the matching component in right.</returns>");
            if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
            WriteLine("public static {0} Min({0} value1, {0} value2)", Name);
            WriteLine("{");
            Indent();
            WriteLine("return new {0}({1});", Name,
                string.Join(", ", Components.Select(component => string.Format("Functions.Min(value1.{0}, value2.{0})", component))));
            Dedent();
            WriteLine("}");
            WriteLine("/// <summary>");
            WriteLine("/// Returns a vector that contains the highest value from each pair of components.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"value1\">The first vector.</param>");
            WriteLine("/// <param name=\"value2\">The second vector.</param>");
            WriteLine("/// <returns>The highest of each component in left and the matching component in right.</returns>");
            if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
            WriteLine("public static {0} Max({0} value1, {0} value2)", Name);
            WriteLine("{");
            Indent();
            WriteLine("return new {0}({1});", Name,
                string.Join(", ", Components.Select(component => string.Format("Functions.Max(value1.{0}, value2.{0})", component))));
            Dedent();
            WriteLine("}");
            WriteLine("/// <summary>");
            WriteLine("/// Constrains each component to a given range.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"value\">A vector to constrain.</param>");
            WriteLine("/// <param name=\"min\">The minimum values for each component.</param>");
            WriteLine("/// <param name=\"max\">The maximum values for each component.</param>");
            WriteLine("/// <returns>A vector with each component constrained to the given range.</returns>");
            if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
            WriteLine("public static {0} Clamp({0} value, {0} min, {0} max)", Name);
            WriteLine("{");
            Indent();
            WriteLine("return new {0}({1});", Name, 
                string.Join(", ", Components.Select(component => string.Format("Functions.Clamp(value.{0}, min.{0}, max.{0})", component))));
            Dedent();
            WriteLine("}");
            if(Type.IsReal)
            {
                WriteLine("/// <summary>");
                WriteLine("/// Constrains each component to the range 0 to 1.");
                WriteLine("/// </summary>");
                WriteLine("/// <param name=\"value\">A vector to saturate.</param>");
                WriteLine("/// <returns>A vector with each component constrained to the range 0 to 1.</returns>");
                if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
                WriteLine("public static {0} Saturate({0} value)", Name);
                WriteLine("{");
                Indent();
                WriteLine("return new {0}({1});", Name, 
                    string.Join(", ", Components.Select(component => string.Format("Functions.Saturate(value.{0})", component))));
                Dedent();
                WriteLine("}");
                WriteLine("/// <summary>");
                WriteLine("/// Returns a vector where each component is the smallest integral value that");
                WriteLine("/// is greater than or equal to the specified component.");
                WriteLine("/// </summary>");
                WriteLine("/// <param name=\"value\">A vector.</param>");
                WriteLine("/// <returns>The ceiling of value.</returns>");
                if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
                WriteLine("public static {0} Ceiling({1} value)", result, Name);
                WriteLine("{");
                Indent();
                WriteLine("return new {0}({1});", result, 
                    string.Join(", ", Components.Select(component => string.Format("Functions.Ceiling(value.{0})", component))));
                Dedent();
                WriteLine("}");
                WriteLine("/// <summary>");
                WriteLine("/// Returns a vector where each component is the largest integral value that");
                WriteLine("/// is less than or equal to the specified component.");
                WriteLine("/// </summary>");
                WriteLine("/// <param name=\"value\">A vector.</param>");
                WriteLine("/// <returns>The floor of value.</returns>");
                if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
                WriteLine("public static {0} Floor({1} value)", result, Name);
                WriteLine("{");
                Indent();
                WriteLine("return new {0}({1});", result, 
                    string.Join(", ", Components.Select(component => string.Format("Functions.Floor(value.{0})", component))));
                Dedent();
                WriteLine("}");
                WriteLine("/// <summary>");
                WriteLine("/// Returns a vector where each component is the integral part of the specified component.");
                WriteLine("/// </summary>");
                WriteLine("/// <param name=\"value\">A vector.</param>");
                WriteLine("/// <returns>The integral of value.</returns>");
                if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
                WriteLine("public static {0} Truncate({1} value)", result, Name);
                WriteLine("{");
                Indent();
                WriteLine("return new {0}({1});", result, 
                    string.Join(", ", Components.Select(component => string.Format("Functions.Truncate(value.{0})", component))));
                Dedent();
                WriteLine("}");
                WriteLine("/// <summary>");
                WriteLine("/// Returns a vector where each component is the fractional part of the specified component.");
                WriteLine("/// </summary>");
                WriteLine("/// <param name=\"value\">A vector.</param>");
                WriteLine("/// <returns>The fractional of value.</returns>");
                if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
                WriteLine("public static {0} Fractional({1} value)", result, Name);
                WriteLine("{");
                Indent();
                WriteLine("return new {0}({1});", result, 
                    string.Join(", ", Components.Select(component => string.Format("Functions.Fractional(value.{0})", component))));
                Dedent();
                WriteLine("}");
                WriteLine("/// <summary>");
                WriteLine("/// Returns a vector where each component is rounded to the nearest integral value.");
                WriteLine("/// </summary>");
                WriteLine("/// <param name=\"value\">A vector.</param>");
                WriteLine("/// <returns>The result of rounding value.</returns>");
                if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
                WriteLine("public static {0} Round({1} value)", result, Name);
                WriteLine("{");
                Indent();
                WriteLine("return new {0}({1});", result, 
                    string.Join(", ", Components.Select(component => string.Format("Functions.Round(value.{0})", component))));
                Dedent();
                WriteLine("}");
                WriteLine("/// <summary>");
                WriteLine("/// Returns a vector where each component is rounded to the nearest integral value.");
                WriteLine("/// </summary>");
                WriteLine("/// <param name=\"value\">A vector.</param>");
                WriteLine("/// <param name=\"digits\">The number of fractional digits in the return value.</param>");
                WriteLine("/// <returns>The result of rounding value.</returns>");
                if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
                WriteLine("public static {0} Round({1} value, int digits)", result, Name);
                WriteLine("{");
                Indent();
                WriteLine("return new {0}({1});", result, 
                    string.Join(", ", Components.Select(component => string.Format("Functions.Round(value.{0}, digits)", component))));
                Dedent();
                WriteLine("}");
                WriteLine("/// <summary>");
                WriteLine("/// Returns a vector where each component is rounded to the nearest integral value.");
                WriteLine("/// </summary>");
                WriteLine("/// <param name=\"value\">A vector.</param>");
                WriteLine("/// <param name=\"mode\">Specification for how to round value if it is midway between two other numbers.</param>");
                WriteLine("/// <returns>The result of rounding value.</returns>");
                if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
                WriteLine("public static {0} Round({1} value, MidpointRounding mode)", result, Name);
                WriteLine("{");
                Indent();
                WriteLine("return new {0}({1});", result, 
                    string.Join(", ", Components.Select(component => string.Format("Functions.Round(value.{0}, mode)", component))));
                Dedent();
                WriteLine("}");
                WriteLine("/// <summary>");
                WriteLine("/// Returns a vector where each component is rounded to the nearest integral value.");
                WriteLine("/// </summary>");
                WriteLine("/// <param name=\"value\">A vector.</param>");
                WriteLine("/// <param name=\"digits\">The number of fractional digits in the return value.</param>");
                WriteLine("/// <param name=\"mode\">Specification for how to round value if it is midway between two other numbers.</param>");
                WriteLine("/// <returns>The result of rounding value.</returns>");
                if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
                WriteLine("public static {0} Round({1} value, int digits, MidpointRounding mode)", result, Name);
                WriteLine("{");
                Indent();
                WriteLine("return new {0}({1});", result, 
                    string.Join(", ", Components.Select(component => string.Format("Functions.Round(value.{0}, digits, mode)", component))));
                Dedent();
                WriteLine("}");
                WriteLine("/// <summary>");
                WriteLine("/// Calculates the reciprocal of each component in the vector.");
                WriteLine("/// </summary>");
                WriteLine("/// <param name=\"value\">A vector.</param>");
                WriteLine("/// <returns>A vector with the reciprocal of each of values components.</returns>");
                if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
                WriteLine("public static {0} Reciprocal({1} value)", result, Name);
                WriteLine("{");
                Indent();
                WriteLine("return new {0}({1});", result,
                    string.Join(", ", Components.Select(component => string.Format("1 / value.{0}", component))));
                Dedent();
                WriteLine("}");
            }
            WriteLine("#endregion");
            #endregion 

            #region Coordinate spaces
            WriteLine("#region Coordinate spaces");

            if (Dimension == 2)
            {
                WriteLine("/// <summary>");
                WriteLine("/// Transforms a vector in cartesian coordinates to polar coordinates.");
                WriteLine("/// </summary>");
                WriteLine("/// <param name=\"value\">The vector to transform.</param>");
                WriteLine("/// <returns>The polar coordinates of value.</returns>");
                if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
                WriteLine("public static PolarCoordinate CartesianToPolar({0} value)", Name);
                WriteLine("{");
                Indent();
                WriteLine("double theta = Functions.Atan2(value.Y, value.X);");
                WriteLine("if (theta < 0)");
                Indent();
                WriteLine("theta += 2 * Constants.Pi;");
                Dedent();
                WriteLine("return new PolarCoordinate(");
                WriteLine("     theta,");
                WriteLine("     (double)Functions.Sqrt(value.X * value.X + value.Y * value.Y));");
                Dedent();
                WriteLine("}");

                if (Type == NumberType.Double)
                {
                    WriteLine("/// <summary>");
                    WriteLine("/// Transforms a vector in polar coordinates to cartesian coordinates.");
                    WriteLine("/// </summary>");
                    WriteLine("/// <param name=\"value\">The vector to transform.</param>");
                    WriteLine("/// <returns>The cartesian coordinates of value.</returns>");
                    if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
                    WriteLine("public static {0} PolarToCartesian(PolarCoordinate value)", Name);
                    WriteLine("{");
                    Indent();
                    WriteLine("return new {0}(", Name);
                    WriteLine("     value.Rho * Functions.Cos(value.Theta), value.Rho * Functions.Sin(value.Theta));");
                    Dedent();
                    WriteLine("}");
                }
            }
            if (Dimension == 3)
            {
                WriteLine("/// <summary>");
                WriteLine("/// Transforms a vector in cartesian coordinates to spherical coordinates.");
                WriteLine("/// </summary>");
                WriteLine("/// <param name=\"value\">The vector to transform.</param>");
                WriteLine("/// <returns>The spherical coordinates of value.</returns>");
                if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
                WriteLine("public static SphericalCoordinate CartesianToSpherical ({0} value)", Name);
                WriteLine("{");
                Indent();
                WriteLine("double r = Functions.Sqrt(value.X * value.X + value.Y * value.Y + value.Z * value.Z);");
                WriteLine("double theta = Functions.Atan2(value.Y, value.X);");
                WriteLine("if (theta < 0)");
                Indent();
                WriteLine("theta += 2 * Constants.Pi;");
                Dedent();
                WriteLine("return new SphericalCoordinate(");
                WriteLine("     (double)Functions.Acos(value.Z / r),");
                WriteLine("     theta,");
                WriteLine("     r);");
                Dedent();
                WriteLine("}");

                if (Type == NumberType.Double)
                {
                    WriteLine("/// <summary>");
                    WriteLine("/// Transforms a vector in spherical coordinates to cartesian coordinates.");
                    WriteLine("/// </summary>");
                    WriteLine("/// <param name=\"value\">The vector to transform.</param>");
                    WriteLine("/// <returns>The cartesian coordinates of value.</returns>");
                    if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
                    WriteLine("public static {0} SphericalToCartesian (SphericalCoordinate value)", Name);
                    WriteLine("{");
                    Indent();
                    WriteLine("return new {0}(", Name);
                    WriteLine("     value.Rho * Functions.Sin(value.Phi) * Functions.Cos(value.Theta),");
                    WriteLine("     value.Rho * Functions.Sin(value.Phi) * Functions.Sin(value.Theta),");
                    WriteLine("     value.Rho * Functions.Cos(value.Phi));");
                    Dedent();
                    WriteLine("}");
                }
            }

            WriteLine("#endregion");
            #endregion

            #region Barycentric, Reflect, Refract
            if(Type.IsReal)
            {
                WriteLine("#region Barycentric, Reflect, Refract");
                WriteLine("/// <summary>");
                WriteLine("/// Returns the Cartesian coordinate for one axis of a point that is defined");
                WriteLine("/// by a given triangle and two normalized barycentric (areal) coordinates.");
                WriteLine("/// </summary>");
                WriteLine("/// <param name=\"value1\">The coordinate of vertex 1 of the defining triangle.</param>");
                WriteLine("/// <param name=\"value2\">The coordinate of vertex 2 of the defining triangle.</param>");
                WriteLine("/// <param name=\"value3\">The coordinate of vertex 3 of the defining triangle.</param>");
                WriteLine("/// <param name=\"amount1\">The normalized barycentric (areal) coordinate b2, equal to the weighting");
                WriteLine("/// factor for vertex 2, the coordinate of which is specified in value2.</param>");
                WriteLine("/// <param name=\"amount2\">The normalized barycentric (areal) coordinate b3, equal to the weighting");
                WriteLine("/// factor for vertex 3, the coordinate of which is specified in value3.</param>");
                WriteLine("/// <returns>Cartesian coordinate of the specified point.</returns>");
                if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
                WriteLine("public static {0} Barycentric({1} value1, {1} value2, {1} value3, {2} amount1, {2} amount2)", result, Name, result.Type);
                WriteLine("{");
                Indent();
                WriteLine("return ((1 - amount1 - amount2) * value1) + (amount1 * value2) + (amount2 * value3);");
                Dedent();
                WriteLine("}");
                WriteLine("/// <summary>");
                WriteLine("/// Returns the reflection of a vector off a surface that has the specified normal.");
                WriteLine("/// </summary>");
                WriteLine("/// <param name=\"vector\">The source vector.</param>");
                WriteLine("/// <param name=\"normal\">Normal of the surface.</param>");
                WriteLine("/// <returns>The reflected vector.</returns>");
                WriteLine("/// <remarks>Reflect only gives the direction of a reflection off a surface, it does not determine");
                WriteLine("/// whether the original vector was close enough to the surface to hit it.</remarks>");
                if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
                WriteLine("public static {0} Reflect({1} vector, {1} normal)", result, Name);
                WriteLine("{");
                Indent();
                WriteLine("return vector - ((2 * Dot(vector, normal)) * normal);");
                Dedent();
                WriteLine("}");
                WriteLine("/// <summary>");
                WriteLine("/// Returns the refraction of a vector off a surface that has the specified normal, and refractive index.");
                WriteLine("/// </summary>");
                WriteLine("/// <param name=\"vector\">The source vector.</param>");
                WriteLine("/// <param name=\"normal\">Normal of the surface.</param>");
                WriteLine("/// <param name=\"index\">The refractive index, destination index over source index.</param>");
                WriteLine("/// <returns>The refracted vector.</returns>");
                WriteLine("/// <remarks>Refract only gives the direction of a refraction off a surface, it does not determine");
                WriteLine("/// whether the original vector was close enough to the surface to hit it.</remarks>");
                if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
                WriteLine("public static {0} Refract({1} vector, {1} normal, {2} index)", result, Name, result.Type);
                WriteLine("{");
                Indent();
                WriteLine("var cos1 = Dot(vector, normal);");
                WriteLine("var radicand = 1 - (index * index) * (1 - (cos1 * cos1));");
                WriteLine("if (radicand < 0)");
                WriteLine("{");
                Indent();
                WriteLine("return {0}.Zero;", result);
                Dedent();
                WriteLine("}");
                WriteLine("return (index * vector) + ((Functions.Sqrt(radicand) - index * cos1) * normal);");
                Dedent();
                WriteLine("}");
                WriteLine("#endregion");
            }
            #endregion

            #region Interpolation
            if (Type.IsReal)
            {
                WriteLine("#region Interpolation");
                //WriteLine("/// <summary>");
                //WriteLine("/// Performs a Hermite spline interpolation.");
                //WriteLine("/// </summary>");
                //WriteLine("/// <param name=\"value1\">First source position.</param>");
                //WriteLine("/// <param name=\"tangent1\">First source tangent.</param>");
                //WriteLine("/// <param name=\"value2\">Second source position.</param>");
                //WriteLine("/// <param name=\"tangent2\">Second source tangent.</param>");
                //WriteLine("/// <param name=\"amount\">Weighting factor.</param>");
                //WriteLine("/// <returns>The result of the Hermite spline interpolation.</returns>");
                //if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); } 
                //WriteLine("public static {0} Hermite({1} value1, {1} tangent1, {1} value2, {1} tangent2, {2} amount)", result, Name, result.Type);
                //WriteLine("{");
                //Indent();
                //WriteLine("var amount2 = amount * amount;");
                //WriteLine("var amount3 = amount2 * amount;");
                //WriteLine("var h00 = 2 * amount3 - 3 * amount2 + 1;");
                //WriteLine("var h10 = amount3 - 2 * amount2 + amount;");
                //WriteLine("var h01 = -2 * amount3 + 3 * amount2;");
                //WriteLine("var h11 = amount3 - amount2;");
                //WriteLine("return h00 * value1 + h10 * tangent1 + h01 * value2 + h11 * tangent2;");
                //Dedent();
                //WriteLine("}");
                //WriteLine("/// <summary>");
                //WriteLine("/// Performs a Catmull-Rom interpolation using the specified positions.");
                //WriteLine("/// </summary>");
                //WriteLine("/// <param name=\"value1\">The first position in the interpolation.</param>");
                //WriteLine("/// <param name=\"value2\">The second position in the interpolation.</param>");
                //WriteLine("/// <param name=\"value3\">The third position in the interpolation.</param>");
                //WriteLine("/// <param name=\"value4\">The fourth position in the interpolation.</param>");
                //WriteLine("/// <param name=\"amount\">Weighting factor.</param>");
                //WriteLine("/// <returns>A vector that is the result of the Catmull-Rom interpolation.</returns>");
                //if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
                //WriteLine("public static {0} CatmullRom({1} value1, {1} value2, {1} value3, {1} value4, {2} amount)", result, Name, result.Type);
                //WriteLine("{");
                //Indent();
                //WriteLine("var tangent0 = (value3 - value1) / 2;");
                //WriteLine("var tangent1 = (value4 - value2) / 2;");
                //WriteLine("return Hermite(value2, tangent0, value3, tangent1, amount);");
                //Dedent();
                //WriteLine("}");
                //WriteLine("/// <summary>");
                //WriteLine("/// Performs a cubic interpolation between two values.");
                //WriteLine("/// </summary>");
                //WriteLine("/// <param name=\"value1\">First values.</param>");
                //WriteLine("/// <param name=\"value2\">Second values.</param>");
                //WriteLine("/// <param name=\"amount\">Value between 0 and 1 indicating the weight of <paramref name=\"value2\"/>.</param>");
                //WriteLine("/// <returns>The cubic interpolation of the two vectors.</returns>");
                //if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
                //WriteLine("public static {0} SmoothStep({1} value1, {1} value2, {2} amount)", result, Name, result.Type);
                //WriteLine("{");
                //Indent();
                //WriteLine("amount = Functions.Saturate(amount);");
                //WriteLine("amount = amount * amount * (3 - 2 * amount);");
                //WriteLine("return Lerp(value1, value2, amount);");
                //Dedent();
                //WriteLine("}");
                WriteLine("/// <summary>");
                WriteLine("/// Performs a linear interpolation between two values.");
                WriteLine("/// </summary>");
                WriteLine("/// <param name=\"value1\">First value.</param>");
                WriteLine("/// <param name=\"value2\">Second value.</param>");
                WriteLine("/// <param name=\"amount\">Value between 0 and 1 indicating the weight of <paramref name=\"value2\"/>.</param>");
                WriteLine("/// <returns>The linear interpolation of the two values.</returns>");
                if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
                WriteLine("public static {0} Lerp({1} value1, {1} value2, {2} amount)", result, Name, result.Type);
                WriteLine("{");
                Indent();
                WriteLine("return (1 - amount) * value1 + amount * value2;");
                Dedent();
                WriteLine("}");
                //WriteLine("/// <summary>");
                //WriteLine("/// Performs a quadratic interpolation between three values.");
                //WriteLine("/// </summary>");
                //WriteLine("/// <param name=\"value1\">First value.</param>");
                //WriteLine("/// <param name=\"value2\">Second value.</param>");
                //WriteLine("/// <param name=\"value3\">Third value.</param>");
                //WriteLine("/// <param name=\"amount\">Value between 0 and 1 indicating the weight towards <paramref name=\"value3\"/>.</param>");
                //WriteLine("/// <returns>The quadratic interpolation of the three values.</returns>");
                //if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
                //WriteLine("public static {0} Qerp({1} value1, {1} value2, {1} value3, {2} amount)", result, Name, result.Type);
                //WriteLine("{");
                //Indent();
                //WriteLine("var p = 2 * value1 - value2 + 2 * value3;");
                //WriteLine("var q = value2 - value3 - 3 * value1;");
                //WriteLine("var r = value1;");
                //WriteLine("var amount2 = amount * amount;");
                //WriteLine("return (p * amount * amount2) + (q * amount) + (r);");
                //Dedent();
                //WriteLine("}");
                //WriteLine("/// <summary>");
                //WriteLine("/// Performs a cubic interpolation between four values.");
                //WriteLine("/// </summary>");
                //WriteLine("/// <param name=\"value1\">First value.</param>");
                //WriteLine("/// <param name=\"value2\">Second value.</param>");
                //WriteLine("/// <param name=\"value3\">Third value.</param>");
                //WriteLine("/// <param name=\"value4\">Fourth value.</param>");
                //WriteLine("/// <param name=\"amount\">Value between 0 and 1 indicating the weight towards <paramref name=\"value4\"/>.</param>");
                //WriteLine("/// <returns>The cubic interpolation of the four values.</returns>");
                //if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
                //WriteLine("public static {0} Cerp({1} value1, {1} value2, {1} value3, {1} value4, {2} amount)", result, Name, result.Type);
                //WriteLine("{");
                //Indent();
                //WriteLine("var p = (value4 - value3) - (value1 - value2);");
                //WriteLine("var q = (value1 - value2) - p;");
                //WriteLine("var r = value3 - value1;");
                //WriteLine("var s = value2;");
                //WriteLine("var amount2 = amount * amount;");
                //WriteLine("return (p * amount * amount2) + (q * amount2) + (r * amount) + (s);");
                //Dedent();
                //WriteLine("}");
                WriteLine("#endregion");
            }
            #endregion
    
            Dedent();
            WriteLine("}");
        }
예제 #4
0
파일: Vector.cs 프로젝트: Frassle/Ibasa
        void Constructors()
        {
            WriteLine("#region Constructors");

            WriteLine("/// <summary>");
            WriteLine("/// Initializes a new instance of the <see cref=\"{0}\"/> using the specified value.", Name);
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"value\">The value that will be assigned to all components.</param>");
            WriteLine("public {0}({1} value)", Name, Type);
            WriteLine("{");
            Indent();
            foreach(var component in Components)
            {
                WriteLine("{0} = value;", component);
            }
            Dedent();
            WriteLine("}");

            if (Dimension == 3)
            {
                WriteLine("/// <summary>");
                WriteLine("/// Initializes a new instance of the <see cref=\"{0}\"/> using the specified vector and values.", Name);
                WriteLine("/// </summary>");
                WriteLine("/// <param name=\"value\">A vector containing the values with which to initialize the X and Y components</param>");
                WriteLine("/// <param name=\"z\">Value for the Z component of the vector.</param>");
                WriteLine("public {0}({1} value, {2} z)", Name, new Vector(Type, 2), Type);
                WriteLine("{");
                WriteLine("\tX = value.X;");
                WriteLine("\tY = value.Y;");
                WriteLine("\tZ = z;");
                WriteLine("}");
            }
            else if (Dimension == 4)
            {
                WriteLine("/// <summary>");
                WriteLine("/// Initializes a new instance of the <see cref=\"{0}\"/> using the specified vector and values.", Name);
                WriteLine("/// </summary>");
                WriteLine("/// <param name=\"value\">A vector containing the values with which to initialize the X and Y components</param>");
                WriteLine("/// <param name=\"z\">Value for the Z component of the vector.</param>");
                WriteLine("/// <param name=\"w\">Value for the W component of the vector.</param>");
                WriteLine("public {0}({1} value, {2} z, {2} w)", Name, new Vector(Type, 2), Type);
                WriteLine("{");
                WriteLine("\tX = value.X;");
                WriteLine("\tY = value.Y;");
                WriteLine("\tZ = z;");
                WriteLine("\tW = w;");
                WriteLine("}");
                WriteLine("/// <summary>");
                WriteLine("/// Initializes a new instance of the <see cref=\"{0}\"/> using the specified vector and values.", Name);
                WriteLine("/// </summary>");
                WriteLine("/// <param name=\"value\">A vector containing the values with which to initialize the X, Y and Z components</param>");
                WriteLine("/// <param name=\"w\">Value for the W component of the vector.</param>");
                WriteLine("public {0}({1} value, {2} w)", Name, new Vector(Type, 3), Type);
                WriteLine("{");
                WriteLine("\tX = value.X;");
                WriteLine("\tY = value.Y;");
                WriteLine("\tZ = value.Z;");
                WriteLine("\tW = w;");
                WriteLine("}");
            }
            else if (Dimension > 4)
            {
                foreach (var size in Sizes.Where(s => s < Dimension))
                {
                    int scalars = Dimension - size;
                    var vector = new Vector(Type, size);

                    WriteLine("/// <summary>");
                    WriteLine("/// Initializes a new instance of the <see cref=\"{0}\"/> using the specified vector and values.", Name);
                    WriteLine("/// </summary>");
                    WriteLine("/// <param name=\"value\">A vector containing the values with which to initialize the first {0} components</param>", size);
                    for (int i = 0; i < scalars; ++i)
                    {
                        WriteLine("/// <param name=\"v{0}\">Value for the {1} component of the vector.</param>", size + i, Components[size + i]);
                    }
                    var args = string.Join(", ", Enumerable.Range(size, Dimension).Select(i => string.Format("{0} v{1}", Type, i)));
                    WriteLine("public {0}({1} value, {2})", Name, vector, args);
                    WriteLine("{");
                    Indent();

                    for (int i = 0; i < size; ++i)
                    {
                        WriteLine("{0} = value.{1};", Components[i], vector.Components[i]);
                    } 
                    for (int i = 0; i < scalars; ++i)
                    {
                        WriteLine("{0} = v{1};", Components[size + i], size + i);
                    }
                    Dedent();
                    WriteLine("}");
                }
            }

            WriteLine("/// <summary>");
            WriteLine("/// Initializes a new instance of the <see cref=\"{0}\"/> using the specified values.", Name);
            WriteLine("/// </summary>");
            foreach (var component in Components)
            {
                WriteLine("/// <param name=\"{0}\">Value for the {1} component of the vector.</param>", component.Name.ToLower(), component);
            }
            WriteLine("public {0}({1})", Name, string.Join(", ", Components.Select(component => Type + " " + component.Name.ToLower())));
            WriteLine("{");
            Indent();
            foreach (var component in Components)
            {
                WriteLine("{0} = {1};", component, component.Name.ToLower());
            }
            Dedent();
            WriteLine("}");

            WriteLine("/// <summary>");
            WriteLine("/// Initializes a new instance of the <see cref=\"{0}\"/> using the specified array.", Name);
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"array\">Array of values for the vector.</param>");
            WriteLine("public {0}({1}[] array)", Name, Type);
            WriteLine("{");
            Indent();
            WriteLine("if (array.Length < 2)");
            Indent();
            WriteLine("throw new ArgumentException(\"Not enough elements in array.\", \"array\");");
            Dedent(); 
            foreach (var component in Components)
            {
                WriteLine("{0} = array[{1}];", component, component.Index);
            }
            Dedent();
            WriteLine("}");

            WriteLine("/// <summary>");
            WriteLine("/// Initializes a new instance of the <see cref=\"{0}\"/> using the specified array.", Name);
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"array\">Array of values for the vector.</param>");
            WriteLine("/// <param name=\"offset\">Offset to start copying values from.</param>");
            WriteLine("public {0}({1}[] array, int offset)", Name, Type);
            WriteLine("{");
            Indent();
            WriteLine("if (array.Length < 2)");
            Indent();
            WriteLine("throw new ArgumentException(\"Not enough elements in array.\", \"array\");");
            Dedent(); 
            foreach (var component in Components)
            {
                WriteLine("{0} = array[offset + {1}];", component, component.Index);
            }
            Dedent();
            WriteLine("}");

            WriteLine("#endregion");
        }
예제 #5
0
파일: Vector.cs 프로젝트: Frassle/Ibasa
        void Operations()
        {
            var result = new Vector(Type.PositiveType, Dimension);

            WriteLine("#region Operations");

            WriteLine("/// <summary>");
            WriteLine("/// Returns the identity of a specified vector.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"value\">A vector.</param>");
            WriteLine("/// <returns>The identity of value.</returns>");
            WriteLine("public static {0} operator +({1} value)", result, Name);
            WriteLine("{");
            Indent();
            WriteLine("return value;");
            Dedent();
            WriteLine("}");

            if (Type.NegativeType != NumberType.Invalid)
            {
                var negVector = new Vector(Type.NegativeType, Dimension);

                WriteLine("/// <summary>");
                WriteLine("/// Returns the additive inverse of a specified vector.");
                WriteLine("/// </summary>");
                WriteLine("/// <param name=\"value\">A vector.</param>");
                WriteLine("/// <returns>The negative of value.</returns>");
                WriteLine("public static {0} operator -({1} value)", negVector, Name);
                WriteLine("{");
                Indent();
                WriteLine("return Vector.Negative(value);");
                Dedent();
                WriteLine("}");
            }

            WriteLine("/// <summary>");
            WriteLine("/// Adds two vectors and returns the result.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"left\">The first value to add.</param>");
            WriteLine("/// <param name=\"right\">The second value to add.</param>");
            WriteLine("/// <returns>The sum of left and right.</returns>");
            WriteLine("public static {0} operator +({1} left, {1} right)", result, Name);
            WriteLine("{");
            Indent();
            WriteLine("return Vector.Add(left, right);");
            Dedent();
            WriteLine("}");

            WriteLine("/// <summary>");
            WriteLine("/// Subtracts one vector from another and returns the result.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"left\">The value to subtract from (the minuend).</param>");
            WriteLine("/// <param name=\"right\">The value to subtract (the subtrahend).</param>");
            WriteLine("/// <returns>The result of subtracting right from left (the difference).</returns>");
            WriteLine("public static {0} operator -({1} left, {1} right)", result, Name);
            WriteLine("{");
            Indent();
            WriteLine("return Vector.Subtract(left, right);");
            Dedent();
            WriteLine("}");

            WriteLine("/// <summary>");
            WriteLine("/// Returns the product of a vector and scalar.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"left\">The vector to multiply.</param>");
            WriteLine("/// <param name=\"right\">The scalar to multiply.</param>");
            WriteLine("/// <returns>The product of the left and right parameters.</returns>");
            WriteLine("public static {0} operator *({1} left, {2} right)", result, Name, result.Type);
            WriteLine("{");
            Indent();
            WriteLine("return Vector.Multiply(left, right);");
            Dedent();
            WriteLine("}");

            WriteLine("/// <summary>");
            WriteLine("/// Returns the product of a scalar and vector.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"left\">The scalar to multiply.</param>");
            WriteLine("/// <param name=\"right\">The vector to multiply.</param>");
            WriteLine("/// <returns>The product of the left and right parameters.</returns>");
            WriteLine("public static {0} operator *({1} left, {2} right)", result, result.Type, Name);
            WriteLine("{");
            Indent();
            WriteLine("return Vector.Multiply(right, left);");
            Dedent();
            WriteLine("}");

            if (Dimension <= 4 && Matrix.Types.Contains(Type))
            {
                foreach (var size in Matrix.Sizes)
                {
                    var matrixA = new Matrix(Type, size, Dimension);
                    var matrixB = new Matrix(Type, Dimension, size);
                    var vector = new Vector(Type, size);

                    WriteLine("/// <summary>");
                    WriteLine("/// Returns the product of a matrix and vector.");
                    WriteLine("/// </summary>");
                    WriteLine("/// <param name=\"left\">The matrix to multiply.</param>");
                    WriteLine("/// <param name=\"right\">The vector to multiply.</param>");
                    WriteLine("/// <returns>The product of the left and right parameters.</returns>");
                    WriteLine("public static {0} operator *({1} left, {2} right)", vector, matrixA, Name);
                    Indent("{");
                    WriteLine("return new {0}({1});", vector, string.Join(", ",
                        vector.Components.Select(i =>
                        string.Join(" + ", Enumerable.Range(0, Dimension).Select(j =>
                            string.Format("left.M{0}{1} * right.{2}", i.Index + 1, j + 1, Components[j]))))));
                    Dedent("}");

                    WriteLine("/// <summary>");
                    WriteLine("/// Returns the product of a matrix and vector.");
                    WriteLine("/// </summary>");
                    WriteLine("/// <param name=\"right\">The vector to multiply.</param>");
                    WriteLine("/// <param name=\"left\">The matrix to multiply.</param>");
                    WriteLine("/// <returns>The product of the left and right parameters.</returns>");
                    WriteLine("public static {0} operator *({1} left, {2} right)", vector, Name, matrixB);
                    Indent("{");
                    WriteLine("return new {0}({1});", vector, string.Join(", ",
                        vector.Components.Select(i =>
                        string.Join(" + ", Enumerable.Range(0, Dimension).Select(j =>
                            string.Format("left.{0} * right.M{1}{2}",Components[j], j + 1, i.Index + 1))))));
                    Dedent("}");
                }
            }

            WriteLine("/// <summary>");
            WriteLine("/// Divides a vector by a scalar and returns the result.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"left\">The vector to be divided (the dividend).</param>");
            WriteLine("/// <param name=\"right\">The scalar to divide by (the divisor).</param>");
            WriteLine("/// <returns>The result of dividing left by right (the quotient).</returns>");
            WriteLine("public static {0} operator /({1} left, {2} right)", result, Name, result.Type);
            WriteLine("{");
            Indent();
            WriteLine("return Vector.Divide(left, right);");
            Dedent();
            WriteLine("}");

            WriteLine("#endregion");
        }
예제 #6
0
파일: Polygon.cs 프로젝트: Frassle/Ibasa
        void Functions()
        {
            WriteLine("/// <summary>");
            WriteLine("/// Provides static methods for polygon functions.");
            WriteLine("/// </summary>");
            WriteLine("public static partial class Polygon");
            WriteLine("{");
            Indent();

            #region Binary
            WriteLine("#region Binary");
            WriteLine("/// <summary>");
            WriteLine("/// Writes the given <see cref=\"{0}\"/> to an <see cref=\"Ibasa.IO.BinaryWriter\">.", Name);
            WriteLine("/// </summary>");
            WriteLine("public static void Write(this Ibasa.IO.BinaryWriter writer, {0} polygon)", Name);
            WriteLine("{");
            Indent();
            WriteLine("var array = polygon.ToArray();");
            WriteLine("writer.Write(array.Length);");
            WriteLine("foreach(var point in array)");
            WriteLine("{");
            Indent();
            WriteLine("writer.Write(point);");
            Dedent();
            WriteLine("}");
            Dedent();
            WriteLine("}");
            WriteLine("/// <summary>");
            WriteLine("/// Reads a <see cref=\"{0}\"/> from an <see cref=\"Ibasa.IO.BinaryReader\">.", Name);
            WriteLine("/// </summary>");
            WriteLine("public static {0} Read{0}(this Ibasa.IO.BinaryReader reader)", Name);
            WriteLine("{");
            Indent();
            WriteLine("var length = reader.ReadInt32();");
            WriteLine("var array = new {0}[length];", Point);
            WriteLine("for (int i=0; i<length; ++i)");
            WriteLine("{");
            Indent();
            WriteLine("array[i] = reader.Read{0}();", Point);
            Dedent();
            WriteLine("}");
            WriteLine("return new {0}(array);", Name);
            Dedent();
            WriteLine("}");
            WriteLine("#endregion");
            #endregion

            #region Equatable
            WriteLine("#region Equatable");
            WriteLine("/// <summary>");
            WriteLine("/// Returns a value that indicates whether two polygons are equal.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"left\">The first polygon to compare.</param>");
            WriteLine("/// <param name=\"right\">The second polygon to compare.</param>");
            WriteLine("/// <returns>true if the left and right are equal; otherwise, false.</returns>");
            WriteLine("public static bool Equals({0} left, {0} right)", Name);
            WriteLine("{");
            Indent();
            WriteLine("return left == right;");
            Dedent();
            WriteLine("}");
            WriteLine("#endregion");
            #endregion

            #region Project
            WriteLine("#region Projection");
            if (Dimension == 2)
            {
                var line = new Line(Type, 1);
                var vector = new Vector(Type, 2);

                WriteLine("/// <summary>");
                WriteLine("/// Projects a polygon onto an axis.");
                WriteLine("/// </summary>");
                WriteLine("/// <param name=\"polygon\">The polygon to project.</param>");
                WriteLine("/// <param name=\"axis\">The axis to project onto.</param>");
                WriteLine("/// <returns>The interval on the axis that the polygon projects onto.</returns>");
                WriteLine("public static {0} Project({1} polygon, {2} axis)", line, Name, vector);
                WriteLine("{");
                Indent();
                WriteLine("var min = {0}.MaxValue;", Type);
                WriteLine("var max = {0}.MinValue;", Type);
                WriteLine("for (int i=0; i < polygon.Count; ++i)");
                WriteLine("{");
                Indent();
                WriteLine("var proj = Vector.Dot(({0})polygon[i], axis);", vector);
                WriteLine("min = Functions.Min(min, proj);");
                WriteLine("max = Functions.Max(max, proj);");
                Dedent();
                WriteLine("}");
                WriteLine("return new {0}(min, max);", line);
                Dedent();
                WriteLine("}");
            }
            //if (Dimension == 3)
            //{
            //    var proj = new Polygon(Type, 2);
            //    var plane = new Plane(Type);

            //    WriteLine("/// <summary>");
            //    WriteLine("/// Projects a polygon onto an plane.");
            //    WriteLine("/// </summary>");
            //    WriteLine("/// <param name=\"polygon\">The polygon to project.</param>");
            //    WriteLine("/// <param name=\"plane\">The plane to project onto.</param>");
            //    WriteLine("/// <returns>The interval on the axis that the polygon projects onto.</returns>");
            //    WriteLine("public static {0} Project({1} polygon, {2} plane)", proj, Name, plane);
            //    WriteLine("{");
            //    Indent();
            //    WriteLine("var min = {0}.MaxValue;", Type);
            //    WriteLine("var max = {0}.MinValue;", Type);
            //    WriteLine("for (int i=0; i < polygon.Count; ++i)");
            //    WriteLine("{");
            //    Indent();
            //    WriteLine("var proj = Vector.Dot(({0})polygon[i], axis);", plane);
            //    WriteLine("min = Functions.Min(min, proj);");
            //    WriteLine("max = Functions.Max(max, proj);");
            //    Dedent();
            //    WriteLine("}");
            //    WriteLine("return new {0}(min, max);", proj);
            //    Dedent();
            //    WriteLine("}");
            //}

            WriteLine("#endregion");
            #endregion

            //public static polygon Intersect(polygon value1, polygon value2)
            //{
            //    int l = Functions.Max(value1.Left, value2.Left);
            //    int r = Functions.Min(value1.Right, value2.Right);
            //    int b = Functions.Max(value1.Bottom, value2.Bottom);
            //    int t = Functions.Min(value1.Top, value2.Top);
            //    int fr = Functions.Max(value1.Front, value2.Front);
            //    int bk = Functions.Min(value1.Back, value2.Back);
            //    if ((r >= l) && (t >= b) && (bk >= fr))
            //    {
            //        return new polygon(l, b, fr, r - l, t - b, bk - fr);
            //    }
            //    return Empty;

            //}
            //public static polygon Union(polygon value1, polygon value2)
            //{
            //    int l = Functions.Max(value1.Left, value2.Left);
            //    int r = Functions.Min(value1.Right, value2.Right);
            //    int b = Functions.Max(value1.Bottom, value2.Bottom);
            //    int t = Functions.Min(value1.Top, value2.Top);
            //    int fr = Functions.Max(value1.Front, value2.Front);
            //    int bk = Functions.Min(value1.Back, value2.Back);
            //    return new polygon(l, b, fr, r - l, t - b, bk - fr);
            //}

            //public static polygon Inflate(polygon polygon, Size3D amount)
            //{
            //    return new polygon(
            //        polygon.X - amount.Width,
            //        polygon.Y - amount.Height,
            //        polygon.Z - amount.Depth,
            //        polygon.Width + (amount.Width * 2),
            //        polygon.Height + (amount.Height * 2),
            //        polygon.Depth + (amount.Depth * 2));
            //}
            //public static polygon Offset(polygon polygon, Point3D amount)
            //{
            //    return new polygon(
            //        polygon.Location + amount,
            //        polygon.Size);
            //}

            //WriteLine("#region Contains");
            //WriteLine("public static bool Contains({0} polygon, {1} point)", Name, new Point(Type, 2));
            //WriteLine("{");
            //Indent();
            //WriteLine("return Vector.AbsoluteSquared(polygon.Center - point) <= polygon.Radius * polygon.Radius;");
            //Dedent();
            //WriteLine("}");
            //WriteLine("#endregion");
            //public bool Contains(polygon polygon)
            //{
            //    return (Left <= polygon.Left) && (Right >= polygon.Right) &&
            //        (Bottom <= polygon.Bottom) && (Top >= polygon.Top) &&
            //        (Front <= polygon.Front) && (Back >= polygon.Back);
            //}
            //public bool Intersects(polygon polygon)
            //{
            //    return (Right > polygon.Left) && (Left < polygon.Right) &&
            //        (Top < polygon.Bottom) && (Bottom < polygon.Top) &&
            //        (Back < polygon.Front) && (Front < polygon.Back);
            //}


            ///// <summary>
            ///// Returns a value that indicates whether two polygons are equal.
            ///// </summary>
            ///// <param name="left">The first polygon to compare.</param>
            ///// <param name="right">The second polygon to compare.</param>
            ///// <returns>true if the left and right are equal; otherwise, false.</returns>
            //public static bool Equals(polygon left, polygon right)
            //{
            //    return left == right;
            //}

            Dedent();
            WriteLine("}");
        }
예제 #7
0
파일: Vector.cs 프로젝트: Frassle/Ibasa
        void Properties()
        {
            WriteLine("#region Properties");
            #region Indexer
            WriteLine("/// <summary>");
            WriteLine("/// Returns the indexed component of this vector.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"index\">The index of the component.</param>");
            WriteLine("/// <returns>The value of the indexed component.</returns>");
            WriteLine("public {0} this[int index]", Type);
            WriteLine("{");
            Indent();
            WriteLine("get");
            WriteLine("{");
            Indent();
            WriteLine("switch (index)");
            WriteLine("{");

            foreach (var component in Components)
            {
                Indent();
                WriteLine("case {0}:", component.Index);
                Indent();
                WriteLine("return {0};", component);
                Dedent();
                Dedent();
            }

            Indent();
            WriteLine("default:");
            Indent();
            WriteLine("throw new IndexOutOfRangeException(\"Indices for {0} run from 0 to {1}, inclusive.\");", Name, Dimension - 1);
            Dedent();
            Dedent();
            WriteLine("}");
            Dedent();
            WriteLine("}");
            Dedent();
            WriteLine("}");
            #endregion

            WriteLine("public {0}[] ToArray()", Type);
            WriteLine("{");
            Indent();
            WriteLine("return new {0}[]", Type);
            WriteLine("{");
            Indent();
            WriteLine(string.Join(", ", (IEnumerable<Component>)Components));
            Dedent();
            WriteLine("};");
            Dedent();
            WriteLine("}");

            #region Swizzles
            if(Dimension <= 4)
            {
                WriteLine("#region Swizzles");
                foreach(var size in Sizes.Where(s => s <= 4))
                {
                    foreach (var permutation in
                        Ibasa.EnumerableExtensions.PermutationsWithRepetition(Components, size))
                    {
                        string components = string.Concat("(", string.Join(", ", permutation), ")");

                        var sizeVector = new Vector(Type, size);

                        WriteLine("/// <summary>");
                        WriteLine("/// Returns the vector {0}.", components);
                        WriteLine("/// </summary>");
                        WriteLine("public {0} {1}", sizeVector, string.Concat(permutation));
                        WriteLine("{");
                        Indent();
                        WriteLine("get");
                        WriteLine("{");
                        Indent();
                        WriteLine("return new {0}{1};", sizeVector, components);
                        Dedent();
                        WriteLine("}");
                        Dedent();
                        WriteLine("}");
                    }
                }
                WriteLine("#endregion");
            }
#endregion
            WriteLine("#endregion");
        }
예제 #8
0
파일: Point.cs 프로젝트: Frassle/Ibasa
        void Functions()
        {
            WriteLine("/// <summary>");
            WriteLine("/// Provides static methods for point functions.");
            WriteLine("/// </summary>");
            WriteLine("public static partial class Point");
            WriteLine("{");
            Indent();

            var result = new Point(Type.PositiveType, Dimension);
            var vector = new Vector(Type.PositiveType, Dimension);

            #region Binary
            WriteLine("#region Binary");
            WriteLine("/// <summary>");
            WriteLine("/// Writes the given <see cref=\"{0}\"/> to an <see cref=\"Ibasa.IO.BinaryWriter\">.", Name);
            WriteLine("/// </summary>");
            WriteLine("public static void Write(this Ibasa.IO.BinaryWriter writer, {0} point)", Name);
            WriteLine("{");
            Indent();
            for (int i = 0; i < Dimension; ++i)
            {
                WriteLine("writer.Write(point.{0});", Components[i]);
            }
            Dedent();
            WriteLine("}");
            WriteLine("/// <summary>");
            WriteLine("/// Reads a <see cref=\"{0}\"/> from an <see cref=\"Ibasa.IO.BinaryReader\">.", Name);
            WriteLine("/// </summary>");
            WriteLine("public static {0} Read{0}(this Ibasa.IO.BinaryReader reader)", Name);
            WriteLine("{");
            Indent();
            WriteLine("return new {0}({1});", Name, string.Join(", ", Components.Select(c => string.Format("reader.Read{0}()", Type.CLRName))));
            Dedent();
            WriteLine("}");
            WriteLine("#endregion");
            #endregion

            #region Operations
            WriteLine("#region Operations");
            WriteLine("/// <summary>");
            WriteLine("/// Adds a point and a vector and returns the result.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"point\">The point value to add.</param>");
            WriteLine("/// <param name=\"vector\">The vector value to add.</param>");
            WriteLine("/// <returns>The sum of left and right.</returns>");
            WriteLine("public static {0} Add({1} point, {2} vector)", result, Name, vector);
            WriteLine("{");
            Indent();
            WriteLine("return new {0}({1});", result,
                string.Join(", ", Components.Select(component => string.Format("point.{0} + vector.{0}", component))));
            Dedent();
            WriteLine("}");

            var subvec = new Vector(result.Type, Dimension);
            WriteLine("/// <summary>");
            WriteLine("/// Subtracts one points from another and returns the result.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"left\">The value to subtract from (the minuend).</param>");
            WriteLine("/// <param name=\"right\">The value to subtract (the subtrahend).</param>");
            WriteLine("/// <returns>The result of subtracting right from left (the difference).</returns>");
            WriteLine("public static {0} Subtract({1} left, {1} right)", subvec, Name);
            WriteLine("{");
            Indent();
            WriteLine("return new {0}({1});", subvec,
                string.Join(", ", Components.Select(component => string.Format("left.{0} - right.{0}", component))));
            Dedent();
            WriteLine("}");

            WriteLine("/// <summary>");
            WriteLine("/// Subtracts a vector from a point and returns the result.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"point\">The point value to subtract from (the minuend).</param>");
            WriteLine("/// <param name=\"vector\">The vector value to subtract (the subtrahend).</param>");
            WriteLine("/// <returns>The result of subtracting vector from point (the difference).</returns>");
            WriteLine("public static {0} Subtract({1} point, {2} vector)", result, Name, vector);
            WriteLine("{");
            Indent();
            WriteLine("return new {0}({1});", result,
                string.Join(", ", Components.Select(component => string.Format("point.{0} - vector.{0}", component))));
            Dedent();
            WriteLine("}");

            WriteLine("/// <summary>");
            WriteLine("/// Returns the product of a point and scalar.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"point\">The point to multiply.</param>");
            WriteLine("/// <param name=\"scalar\">The scalar to multiply.</param>");
            WriteLine("/// <returns>The product of the left and right parameters.</returns>");
            WriteLine("public static {0} Multiply({1} point, {2} scalar)", result, Name, result.Type);
            WriteLine("{");
            Indent();
            WriteLine("return new {0}({1});", result,
                string.Join(", ", Components.Select(component => string.Format("point.{0} * scalar", component))));
            Dedent();
            WriteLine("}");

            WriteLine("/// <summary>");
            WriteLine("/// Divides a point by a scalar and returns the result.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"point\">The point to be divided (the dividend).</param>");
            WriteLine("/// <param name=\"scalar\">The scalar to divide by (the divisor).</param>");
            WriteLine("/// <returns>The result of dividing left by right (the quotient).</returns>");
            WriteLine("public static {0} Divide({1} point, {2} scalar)", result, Name, result.Type);
            WriteLine("{");
            Indent();
            WriteLine("return new {0}({1});", result,
                string.Join(", ", Components.Select(component => string.Format("point.{0} / scalar", component))));
            Dedent();
            WriteLine("}");

            // affine sums
            {
                var real_point = new Point(Type.RealType, Dimension);

                WriteLine("public static {0} Sum(IEnumerable<{1}> points, IEnumerable<{2}> weights)", real_point, Name, Type.RealType);
                WriteLine("{");
                Indent();
                WriteLine("Contract.Requires(weights.Sum() == 1.0);");
                foreach (var component in Components)
                {
                    WriteLine("{0} sum{1} = 0;", Type.RealType, component);
                }
                WriteLine("var point = points.GetEnumerator();");
                WriteLine("var weight = weights.GetEnumerator();");
                WriteLine("while(point.MoveNext() && weight.MoveNext())");
                WriteLine("{");
                Indent();
                WriteLine("var p = point.Current;");
                WriteLine("var w = weight.Current;");
                foreach (var component in Components)
                {
                    WriteLine("sum{0} += p.{0} * w;", component);
                }
                Dedent();
                WriteLine("}");
                WriteLine("return new {0}({1});", real_point, string.Join(", ", Components.Select(c => string.Format("sum{0}", c))));
                Dedent();
                WriteLine("}");

                WriteLine("public static {0} Sum(IEnumerable<{1}> points, {2} weight)", real_point, Name, Type.RealType);
                WriteLine("{");
                Indent();
                WriteLine("Contract.Requires(weight * points.Count() == 1.0);");
                foreach (var component in Components)
                {
                    WriteLine("{0} sum{1} = 0;", Type.RealType, component);
                }
                WriteLine("foreach (var point in points)");
                WriteLine("{");
                Indent();
                foreach (var component in Components)
                {
                    WriteLine("sum{0} += point.{0} * weight;", component);
                }
                Dedent();
                WriteLine("}");
                WriteLine("return new {0}({1});", real_point, string.Join(", ", Components.Select(c => string.Format("sum{0}", c))));
                Dedent();
                WriteLine("}");
            }
            WriteLine("#endregion");
            #endregion

            #region Equatable
            WriteLine("#region Equatable");
            WriteLine("/// <summary>");
            WriteLine("/// Returns a value that indicates whether two points are equal.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"left\">The first point to compare.</param>");
            WriteLine("/// <param name=\"right\">The second point to compare.</param>");
            WriteLine("/// <returns>true if the left and right are equal; otherwise, false.</returns>");
            WriteLine("public static bool Equals({0} left, {0} right)", Name);
            WriteLine("{");
            Indent();
            WriteLine("return left == right;");
            Dedent();
            WriteLine("}");
            WriteLine("#endregion");
            #endregion

            #region Distance
            WriteLine("#region Distance");
            WriteLine("/// <summary>");
            WriteLine("/// Returns the distance between two points.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"value1\">The first point.</param>");
            WriteLine("/// <param name=\"value2\">The second point.</param>");
            WriteLine("/// <returns>The distance between value1 and value2.</returns>");
            WriteLine("public static {0} Distance({1} value1, {1} value2)", Type.RealType, Name);
            WriteLine("{");
            Indent();
            WriteLine("return Vector.Absolute(value2 - value1);");
            Dedent();
            WriteLine("}");
            WriteLine("/// <summary>");
            WriteLine("/// Returns the squared distance between two points.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"value1\">The first point.</param>");
            WriteLine("/// <param name=\"value2\">The second point.</param>");
            WriteLine("/// <returns>The squared distance between value1 and value2.</returns>");
            WriteLine("public static {0} DistanceSquared({1} value1, {1} value2)", result.Type, Name);
            WriteLine("{");
            Indent();
            WriteLine("return Vector.AbsoluteSquared(value2 - value1);");
            Dedent();
            WriteLine("}");
            {
                var abs = Components.Select(component => string.Format("Functions.Abs(value2.{0} - value1.{0})", component.Name));
                var sum = string.Join("+", abs);

                WriteLine("/// <summary>");
                WriteLine("/// Returns the manhatten distance between two points.");
                WriteLine("/// </summary>");
                WriteLine("/// <param name=\"value1\">The first point.</param>");
                WriteLine("/// <param name=\"value2\">The second point.</param>");
                WriteLine("/// <returns>The manhatten distance between value1 and value2.</returns>");
                WriteLine("public static {0} ManhattenDistance({1} value1, {1} value2)", result.Type, Name);
                WriteLine("{");
                Indent();
                WriteLine("return {0};", sum);
                Dedent();
                WriteLine("}");
            }
            WriteLine("#endregion");
            #endregion

            #region Test
            WriteLine("#region Test");
            WriteLine("/// <summary>");
            WriteLine("/// Determines whether all components of a point are non-zero.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"value\">A point.</param>");
            WriteLine("/// <returns>true if all components are non-zero; false otherwise.</returns>");
            if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
            WriteLine("public static bool All({0} value)", Name);
            WriteLine("{");
            Indent();
            WriteLine("return {0};",
                string.Join(" && ", Components.Select(component => string.Format("value.{0} != 0", component))));
            Dedent();
            WriteLine("}");
            WriteLine("/// <summary>");
            WriteLine("/// Determines whether all components of a point satisfy a condition.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"value\">A point.</param>");
            WriteLine("/// <param name=\"predicate\">A function to test each component for a condition.</param>");
            WriteLine("/// <returns>true if every component of the point passes the test in the specified");
            WriteLine("/// predicate; otherwise, false.</returns>");
            if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
            WriteLine("public static bool All({0} value, Predicate<{1}> predicate)", Name, Type);
            WriteLine("{");
            Indent();
            WriteLine("return {0};",
                string.Join(" && ", Components.Select(component => string.Format("predicate(value.{0})", component))));
            Dedent();
            WriteLine("}");
            WriteLine("/// <summary>");
            WriteLine("/// Determines whether any component of a point is non-zero.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"value\">A point.</param>");
            WriteLine("/// <returns>true if any components are non-zero; false otherwise.</returns>");
            if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
            WriteLine("public static bool Any({0} value)", Name);
            WriteLine("{");
            Indent();
            WriteLine("return {0};",
                string.Join(" || ", Components.Select(component => string.Format("value.{0} != 0", component))));
            Dedent();
            WriteLine("}");
            WriteLine("/// <summary>");
            WriteLine("/// Determines whether any components of a point satisfy a condition.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"value\">A point.</param>");
            WriteLine("/// <param name=\"predicate\">A function to test each component for a condition.</param>");
            WriteLine("/// <returns>true if any component of the point passes the test in the specified");
            WriteLine("/// predicate; otherwise, false.</returns>");
            if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
            WriteLine("public static bool Any({0} value, Predicate<{1}> predicate)", Name, Type);
            WriteLine("{");
            Indent();
            WriteLine("return {0};",
                string.Join(" || ", Components.Select(component => string.Format("predicate(value.{0})", component))));
            Dedent();
            WriteLine("}");
            WriteLine("#endregion");
            #endregion

            #region Per component
            WriteLine("#region Per component");

            WriteLine("#region Map");
            foreach (var type in Shapes.Types)
            {
                var map = new Point(type, Dimension);

                WriteLine("/// <summary>");
                WriteLine("/// Maps the components of a point and returns the result.");
                WriteLine("/// </summary>");
                WriteLine("/// <param name=\"value\">The point to map.</param>");
                WriteLine("/// <param name=\"mapping\">A mapping function to apply to each component.</param>");
                WriteLine("/// <returns>The result of mapping each component of value.</returns>");
                if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
                WriteLine("public static {0} Map({1} value, Func<{2}, {3}> mapping)", map, Name, Type, map.Type);
                WriteLine("{");
                Indent();
                WriteLine("return new {0}({1});", map,
                    string.Join(", ", Components.Select(component => string.Format("mapping(value.{0})", component))));
                Dedent();
                WriteLine("}");
            }
            WriteLine("#endregion");

            WriteLine("/// <summary>");
            WriteLine("/// Multiplys the components of two points and returns the result.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"left\">The first point to modulate.</param>");
            WriteLine("/// <param name=\"right\">The second point to modulate.</param>");
            WriteLine("/// <returns>The result of multiplying each component of left by the matching component in right.</returns>");
            if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
            WriteLine("public static {0} Modulate({1} left, {1} right)", result, Name);
            WriteLine("{");
            Indent();
            WriteLine("return new {0}({1});", result,
                string.Join(", ", Components.Select(component => string.Format("left.{0} * right.{0}", component))));
            Dedent();
            WriteLine("}");
            WriteLine("/// <summary>");
            WriteLine("/// Returns the absolute value (per component).");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"value\">A point.</param>");
            WriteLine("/// <returns>The absolute value (per component) of value.</returns>");
            if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
            WriteLine("public static {0} Abs({0} value)", Name);
            WriteLine("{");
            Indent();
            WriteLine("return new {0}({1});", Name,
                string.Join(", ", Components.Select(component => string.Format("Functions.Abs(value.{0})", component))));
            Dedent();
            WriteLine("}");
            WriteLine("/// <summary>");
            WriteLine("/// Returns a point that contains the lowest value from each pair of components.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"value1\">The first point.</param>");
            WriteLine("/// <param name=\"value2\">The second point.</param>");
            WriteLine("/// <returns>The lowest of each component in left and the matching component in right.</returns>");
            if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
            WriteLine("public static {0} Min({0} value1, {0} value2)", Name);
            WriteLine("{");
            Indent();
            WriteLine("return new {0}({1});", Name,
                string.Join(", ", Components.Select(component => string.Format("Functions.Min(value1.{0}, value2.{0})", component))));
            Dedent();
            WriteLine("}");
            WriteLine("/// <summary>");
            WriteLine("/// Returns a point that contains the highest value from each pair of components.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"value1\">The first point.</param>");
            WriteLine("/// <param name=\"value2\">The second point.</param>");
            WriteLine("/// <returns>The highest of each component in left and the matching component in right.</returns>");
            if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
            WriteLine("public static {0} Max({0} value1, {0} value2)", Name);
            WriteLine("{");
            Indent();
            WriteLine("return new {0}({1});", Name,
                string.Join(", ", Components.Select(component => string.Format("Functions.Max(value1.{0}, value2.{0})", component))));
            Dedent();
            WriteLine("}");
            WriteLine("/// <summary>");
            WriteLine("/// Constrains each component to a given range.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"value\">A point to constrain.</param>");
            WriteLine("/// <param name=\"min\">The minimum values for each component.</param>");
            WriteLine("/// <param name=\"max\">The maximum values for each component.</param>");
            WriteLine("/// <returns>A point with each component constrained to the given range.</returns>");
            if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
            WriteLine("public static {0} Clamp({0} value, {0} min, {0} max)", Name);
            WriteLine("{");
            Indent();
            WriteLine("return new {0}({1});", Name,
                string.Join(", ", Components.Select(component => string.Format("Functions.Clamp(value.{0}, min.{0}, max.{0})", component))));
            Dedent();
            WriteLine("}");
            if (Type.IsReal)
            {
                WriteLine("/// <summary>");
                WriteLine("/// Constrains each component to the range 0 to 1.");
                WriteLine("/// </summary>");
                WriteLine("/// <param name=\"value\">A point to saturate.</param>");
                WriteLine("/// <returns>A point with each component constrained to the range 0 to 1.</returns>");
                if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
                WriteLine("public static {0} Saturate({0} value)", Name);
                WriteLine("{");
                Indent();
                WriteLine("return new {0}({1});", Name,
                    string.Join(", ", Components.Select(component => string.Format("Functions.Saturate(value.{0})", component))));
                Dedent();
                WriteLine("}");
                WriteLine("/// <summary>");
                WriteLine("/// Returns a point where each component is the smallest integral value that");
                WriteLine("/// is greater than or equal to the specified component.");
                WriteLine("/// </summary>");
                WriteLine("/// <param name=\"value\">A point.</param>");
                WriteLine("/// <returns>The ceiling of value.</returns>");
                if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
                WriteLine("public static {0} Ceiling({1} value)", result, Name);
                WriteLine("{");
                Indent();
                WriteLine("return new {0}({1});", result,
                    string.Join(", ", Components.Select(component => string.Format("Functions.Ceiling(value.{0})", component))));
                Dedent();
                WriteLine("}");
                WriteLine("/// <summary>");
                WriteLine("/// Returns a point where each component is the largest integral value that");
                WriteLine("/// is less than or equal to the specified component.");
                WriteLine("/// </summary>");
                WriteLine("/// <param name=\"value\">A point.</param>");
                WriteLine("/// <returns>The floor of value.</returns>");
                if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
                WriteLine("public static {0} Floor({1} value)", result, Name);
                WriteLine("{");
                Indent();
                WriteLine("return new {0}({1});", result,
                    string.Join(", ", Components.Select(component => string.Format("Functions.Floor(value.{0})", component))));
                Dedent();
                WriteLine("}");
                WriteLine("/// <summary>");
                WriteLine("/// Returns a point where each component is the integral part of the specified component.");
                WriteLine("/// </summary>");
                WriteLine("/// <param name=\"value\">A point.</param>");
                WriteLine("/// <returns>The integral of value.</returns>");
                if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
                WriteLine("public static {0} Truncate({1} value)", result, Name);
                WriteLine("{");
                Indent();
                WriteLine("return new {0}({1});", result,
                    string.Join(", ", Components.Select(component => string.Format("Functions.Truncate(value.{0})", component))));
                Dedent();
                WriteLine("}");
                WriteLine("/// <summary>");
                WriteLine("/// Returns a point where each component is the fractional part of the specified component.");
                WriteLine("/// </summary>");
                WriteLine("/// <param name=\"value\">A point.</param>");
                WriteLine("/// <returns>The fractional of value.</returns>");
                if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
                WriteLine("public static {0} Fractional({1} value)", result, Name);
                WriteLine("{");
                Indent();
                WriteLine("return new {0}({1});", result,
                    string.Join(", ", Components.Select(component => string.Format("Functions.Fractional(value.{0})", component))));
                Dedent();
                WriteLine("}");
                WriteLine("/// <summary>");
                WriteLine("/// Returns a point where each component is rounded to the nearest integral value.");
                WriteLine("/// </summary>");
                WriteLine("/// <param name=\"value\">A point.</param>");
                WriteLine("/// <returns>The result of rounding value.</returns>");
                if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
                WriteLine("public static {0} Round({1} value)", result, Name);
                WriteLine("{");
                Indent();
                WriteLine("return new {0}({1});", result,
                    string.Join(", ", Components.Select(component => string.Format("Functions.Round(value.{0})", component))));
                Dedent();
                WriteLine("}");
                WriteLine("/// <summary>");
                WriteLine("/// Returns a point where each component is rounded to the nearest integral value.");
                WriteLine("/// </summary>");
                WriteLine("/// <param name=\"value\">A point.</param>");
                WriteLine("/// <param name=\"digits\">The number of fractional digits in the return value.</param>");
                WriteLine("/// <returns>The result of rounding value.</returns>");
                if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
                WriteLine("public static {0} Round({1} value, int digits)", result, Name);
                WriteLine("{");
                Indent();
                WriteLine("return new {0}({1});", result,
                    string.Join(", ", Components.Select(component => string.Format("Functions.Round(value.{0}, digits)", component))));
                Dedent();
                WriteLine("}");
                WriteLine("/// <summary>");
                WriteLine("/// Returns a point where each component is rounded to the nearest integral value.");
                WriteLine("/// </summary>");
                WriteLine("/// <param name=\"value\">A point.</param>");
                WriteLine("/// <param name=\"mode\">Specification for how to round value if it is midway between two other numbers.</param>");
                WriteLine("/// <returns>The result of rounding value.</returns>");
                if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
                WriteLine("public static {0} Round({1} value, MidpointRounding mode)", result, Name);
                WriteLine("{");
                Indent();
                WriteLine("return new {0}({1});", result,
                    string.Join(", ", Components.Select(component => string.Format("Functions.Round(value.{0}, mode)", component))));
                Dedent();
                WriteLine("}");
                WriteLine("/// <summary>");
                WriteLine("/// Returns a point where each component is rounded to the nearest integral value.");
                WriteLine("/// </summary>");
                WriteLine("/// <param name=\"value\">A point.</param>");
                WriteLine("/// <param name=\"digits\">The number of fractional digits in the return value.</param>");
                WriteLine("/// <param name=\"mode\">Specification for how to round value if it is midway between two other numbers.</param>");
                WriteLine("/// <returns>The result of rounding value.</returns>");
                if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
                WriteLine("public static {0} Round({1} value, int digits, MidpointRounding mode)", result, Name);
                WriteLine("{");
                Indent();
                WriteLine("return new {0}({1});", result,
                    string.Join(", ", Components.Select(component => string.Format("Functions.Round(value.{0}, digits, mode)", component))));
                Dedent();
                WriteLine("}");
                WriteLine("/// <summary>");
                WriteLine("/// Calculates the reciprocal of each component in the point.");
                WriteLine("/// </summary>");
                WriteLine("/// <param name=\"value\">A point.</param>");
                WriteLine("/// <returns>A point with the reciprocal of each of values components.</returns>");
                if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
                WriteLine("public static {0} Reciprocal({1} value)", result, Name);
                WriteLine("{");
                Indent();
                WriteLine("return new {0}({1});", result,
                    string.Join(", ", Components.Select(component => string.Format("1 / value.{0}", component))));
                Dedent();
                WriteLine("}");
            }
            WriteLine("#endregion");
            #endregion

            #region Coordinate spaces
            WriteLine("#region Coordinate spaces");

            if (Dimension == 2)
            {
                WriteLine("/// <summary>");
                WriteLine("/// Transforms a point in cartesian coordinates to polar coordinates.");
                WriteLine("/// </summary>");
                WriteLine("/// <param name=\"value\">The point to transform.</param>");
                WriteLine("/// <returns>The polar coordinates of value.</returns>");
                if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
                WriteLine("public static PolarCoordinate CartesianToPolar({0} value)", Name);
                WriteLine("{");
                Indent();
                WriteLine("double theta = Functions.Atan2(value.Y, value.X);");
                WriteLine("if (theta < 0)");
                Indent();
                WriteLine("theta += 2 * Constants.Pi;");
                Dedent();
                WriteLine("return new PolarCoordinate(");
                WriteLine("     theta,");
                WriteLine("     (double)Functions.Sqrt(value.X * value.X + value.Y * value.Y));");
                Dedent();
                WriteLine("}");

                if (Type == NumberType.Double)
                {
                    WriteLine("/// <summary>");
                    WriteLine("/// Transforms a point in polar coordinates to cartesian coordinates.");
                    WriteLine("/// </summary>");
                    WriteLine("/// <param name=\"value\">The point to transform.</param>");
                    WriteLine("/// <returns>The cartesian coordinates of value.</returns>");
                    if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
                    WriteLine("public static {0} PolarToCartesian(PolarCoordinate value)", Name);
                    WriteLine("{");
                    Indent();
                    WriteLine("return new {0}(", Name);
                    WriteLine("     value.Rho * Functions.Cos(value.Theta), value.Rho * Functions.Sin(value.Theta));");
                    Dedent();
                    WriteLine("}");
                }
            }
            if (Dimension == 3)
            {
                WriteLine("/// <summary>");
                WriteLine("/// Transforms a point in cartesian coordinates to spherical coordinates.");
                WriteLine("/// </summary>");
                WriteLine("/// <param name=\"value\">The point to transform.</param>");
                WriteLine("/// <returns>The spherical coordinates of value.</returns>");
                if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
                WriteLine("public static SphericalCoordinate CartesianToSpherical ({0} value)", Name);
                WriteLine("{");
                Indent();
                WriteLine("double r = Functions.Sqrt(value.X * value.X + value.Y * value.Y + value.Z * value.Z);");
                WriteLine("double theta = Functions.Atan2(value.Y, value.X);");
                WriteLine("if (theta < 0)");
                Indent();
                WriteLine("theta += 2 * Constants.Pi;");
                Dedent();
                WriteLine("return new SphericalCoordinate(");
                WriteLine("     r,");
                WriteLine("     (double)Functions.Acos(value.Z / r),");
                WriteLine("     theta);");
                Dedent();
                WriteLine("}");

                if (Type == NumberType.Double)
                {
                    WriteLine("/// <summary>");
                    WriteLine("/// Transforms a point in spherical coordinates to cartesian coordinates.");
                    WriteLine("/// </summary>");
                    WriteLine("/// <param name=\"value\">The point to transform.</param>");
                    WriteLine("/// <returns>The cartesian coordinates of value.</returns>");
                    if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
                    WriteLine("public static {0} SphericalToCartesian (SphericalCoordinate value)", Name);
                    WriteLine("{");
                    Indent();
                    WriteLine("return new {0}(", Name);
                    WriteLine("     value.Rho * Functions.Sin(value.Phi) * Functions.Cos(value.Theta),");
                    WriteLine("     value.Rho * Functions.Sin(value.Phi) * Functions.Sin(value.Theta),");
                    WriteLine("     value.Rho * Functions.Cos(value.Phi));");
                    Dedent();
                    WriteLine("}");
                }
            }

            WriteLine("#endregion");
            #endregion

            #region Barycentric
            //if(Type.IsReal)
            //{
            //    WriteLine("#region Barycentric");
            //    WriteLine("/// <summary>");
            //    WriteLine("/// Returns the Cartesian coordinate for one axis of a point that is defined");
            //    WriteLine("/// by a given triangle and two normalized barycentric (areal) coordinates.");
            //    WriteLine("/// </summary>");
            //    WriteLine("/// <param name=\"value1\">The coordinate of vertex 1 of the defining triangle.</param>");
            //    WriteLine("/// <param name=\"value2\">The coordinate of vertex 2 of the defining triangle.</param>");
            //    WriteLine("/// <param name=\"value3\">The coordinate of vertex 3 of the defining triangle.</param>");
            //    WriteLine("/// <param name=\"amount1\">The normalized barycentric (areal) coordinate b2, equal to the weighting");
            //    WriteLine("/// factor for vertex 2, the coordinate of which is specified in value2.</param>");
            //    WriteLine("/// <param name=\"amount2\">The normalized barycentric (areal) coordinate b3, equal to the weighting");
            //    WriteLine("/// factor for vertex 3, the coordinate of which is specified in value3.</param>");
            //    WriteLine("/// <returns>Cartesian coordinate of the specified point.</returns>");
            //    if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
            //    WriteLine("public static {0} Barycentric({1} value1, {1} value2, {1} value3, {2} amount1, {2} amount2)", result, Name, result.Type);
            //    WriteLine("{");
            //    Indent();
            //    WriteLine("return ((1 - amount1 - amount2) * value1) + (amount1 * value2) + (amount2 * value3);");
            //    Dedent();
            //    WriteLine("}");
            //    WriteLine("#endregion");
            //}
            #endregion

            #region Project

            WriteLine("#region Project");

            WriteLine("/// <summary>");
            WriteLine("/// Projects a point onto a vector, returns the distance of the projection from the origin.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"vector\">The vector to project onto.</param>");
            WriteLine("/// <param name=\"point\">The point to project.</param>");
            WriteLine("/// <returns>The distance from the origin of the projection.</returns>");
            if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
            WriteLine("public static {0} Project({1} point, {2} vector)", result.Type, Name, new Vector(Type, Dimension));
            WriteLine("{");
            Indent();
            WriteLine("return {0};", string.Join(" + ", Components.Select(component => string.Format("vector.{0} * point.{0}", component))));
            Dedent();
            WriteLine("}");

            WriteLine("#endregion");
            #endregion

            #region Interpolation
            if (Type.IsReal)
            {
                WriteLine("#region Interpolation");
                WriteLine("/// <summary>");
                WriteLine("/// Performs a linear interpolation between two points.");
                WriteLine("/// </summary>");
                WriteLine("/// <param name=\"point1\">First point.</param>");
                WriteLine("/// <param name=\"point2\">Second point.</param>");
                WriteLine("/// <param name=\"amount\">Value between 0 and 1 indicating the weight of <paramref name=\"value2\"/>.</param>");
                WriteLine("/// <returns>The linear interpolation of the two points.</returns>");
                if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
                WriteLine("public static {0} Lerp({1} point1, {1} point2, {2} amount)", result, Name, result.Type);
                WriteLine("{");
                Indent();
                WriteLine("return point1 + (point2 - point1) * amount;");
                Dedent();
                WriteLine("}");
                WriteLine("#endregion");
            }
            #endregion

            Dedent();
            WriteLine("}");
        }
예제 #9
0
파일: Quaternion.cs 프로젝트: Frassle/Ibasa
        void Functions()
        {
            WriteLine("/// <summary>");
            WriteLine("/// Provides static methods for quaternion functions.");
            WriteLine("/// </summary>");
            WriteLine("public static partial class Quaternion");
            WriteLine("{");
            Indent();

            var result = new Quaternion(Type.PositiveType);

            #region Factory

            WriteLine("#region Factory");

            WriteLine("/// <summary>");
            WriteLine("/// Initializes a new instance of the <see cref=\"{0}\"/> structure given a rotation and an axis.", Name);
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"axis\">The axis of rotation.</param>");
            WriteLine("/// <param name=\"angle\">The angle of rotation.</param>");
            WriteLine("/// <returns>The newly created quaternion.</returns>");
            WriteLine("public static {0} FromRotationAxis({1} axis, {2} angle)", Name, new Vector(Type, 3), Type);
            Indent("{");
            WriteLine("axis = Vector.Normalize(axis);");
            WriteLine("var half = angle * 0.5f;");
            WriteLine("var sin =  Functions.Sin(half);");
            WriteLine("var cos =  Functions.Cos(half);");
            WriteLine("return new {0}(cos, axis.X * sin, axis.Y * sin, axis.Z * sin);", Name);
            Dedent("}");

            WriteLine("/// <summary>");
            WriteLine("/// Initializes a new instance of the <see cref=\"{0}\"/> structure given a yaw, pitch, and roll value.", Name);
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"yaw\">The yaw of rotation.</param>");
            WriteLine("/// <param name=\"pitch\">The pitch of rotation.</param>");
            WriteLine("/// <param name=\"roll\">The roll of rotation.</param>");
            WriteLine("/// <returns>The newly created quaternion.</returns>");
            WriteLine("public static {0} FromRotationAngles({1} yaw, {1} pitch, {1} roll)", Name, Type);
            Indent("{");
            WriteLine("var halfRoll = roll * 0.5f;");
            WriteLine("var sinRoll = Functions.Sin(halfRoll);");
            WriteLine("var cosRoll = Functions.Cos(halfRoll);");
            WriteLine("var halfPitch = pitch * 0.5f;");
            WriteLine("var sinPitch = Functions.Sin(halfPitch);");
            WriteLine("var cosPitch = Functions.Cos(halfPitch);");
            WriteLine("var halfYaw = yaw * 0.5f;");
            WriteLine("var sinYaw = Functions.Sin(halfYaw);");
            WriteLine("var cosYaw = Functions.Cos(halfYaw);");
            WriteLine("return new {0}(", Name);
            WriteLine("\t(cosYaw * cosPitch * cosRoll) + (sinYaw * sinPitch * sinRoll),");
            WriteLine("\t(cosYaw * sinPitch * cosRoll) + (sinYaw * cosPitch * sinRoll),");
            WriteLine("\t(sinYaw * cosPitch * cosRoll) - (cosYaw * sinPitch * sinRoll),");
            WriteLine("\t(cosYaw * cosPitch * sinRoll) - (sinYaw * sinPitch * cosRoll));");
            Dedent("}");

            WriteLine("/// <summary>");
		    WriteLine("/// Initializes a new instance of the <see cref=\"{0}\"/> structure given a rotation matrix.", Name);
		    WriteLine("/// </summary>");
		    WriteLine("/// <param name=\"matrix\">The rotation matrix.</param>");
		    WriteLine("/// <returns>The newly created quaternion.</returns>");
		    WriteLine("public static {0} FromMatrix({1} matrix)", Name, new Matrix(Type, 3,3));
		    Indent("{");
            WriteLine("var a = Functions.Sqrt(Functions.Max(0, 1 + matrix[0, 0] + matrix[1, 1] + matrix[2, 2])) / 2;");
            WriteLine("var b = Functions.Sqrt(Functions.Max(0, 1 + matrix[0, 0] - matrix[1, 1] - matrix[2, 2])) / 2;");
            WriteLine("var c = Functions.Sqrt(Functions.Max(0, 1 - matrix[0, 0] + matrix[1, 1] - matrix[2, 2])) / 2;");
            WriteLine("var d = Functions.Sqrt(Functions.Max(0, 1 - matrix[0, 0] - matrix[1, 1] + matrix[2, 2])) / 2;");
            WriteLine("b *= Functions.Sign(b * (matrix[2, 1] - matrix[1, 2]));");
            WriteLine("c *= Functions.Sign(c * (matrix[0, 2] - matrix[2, 0]));");
            WriteLine("d *= Functions.Sign(d * (matrix[1, 0] - matrix[0, 1]));");
            WriteLine("return new {0}(a, b, c, d);", Name);
		    Dedent("}");

            WriteLine("/// <summary>");
            WriteLine("/// Initializes a new instance of the <see cref=\"{0}\"/> structure given a direction and up axis.", Name);
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"direction\">The direction vector.</param>");
            WriteLine("/// <param name=\"up\">The up axis.</param>");
            WriteLine("/// <returns>The newly created quaternion.</returns>");
            WriteLine("public static {0} FromOrientation({1} direction, {1} up)", Name, new Vector(Type, 3));
            Indent("{");
            WriteLine("var zaxis = Vector.Normalize(direction);");
            WriteLine("var xaxis = Vector.Normalize(Vector.Cross(up, zaxis));");
            WriteLine("var yaxis = Vector.Cross(zaxis, xaxis);");
            WriteLine("var a = Functions.Sqrt(Functions.Max(0, 1 + xaxis.X + yaxis.Y + zaxis.Z)) / 2;");
            WriteLine("var b = Functions.Sqrt(Functions.Max(0, 1 + xaxis.X - yaxis.Y - zaxis.Z)) / 2;");
            WriteLine("var c = Functions.Sqrt(Functions.Max(0, 1 - xaxis.X + yaxis.Y - zaxis.Z)) / 2;");
            WriteLine("var d = Functions.Sqrt(Functions.Max(0, 1 - xaxis.X - yaxis.Y + zaxis.Z)) / 2;");
            WriteLine("b *= Functions.Sign(b * (yaxis.Z - zaxis.Y));");
            WriteLine("c *= Functions.Sign(c * (zaxis.X - xaxis.Z));");
            WriteLine("d *= Functions.Sign(d * (xaxis.Y - yaxis.X));");
            WriteLine("return new {0}(a, b, c, d);", Name);
            Dedent("}");

            WriteLine("#endregion");
            #endregion

            #region Binary
            WriteLine("#region Binary");
            WriteLine("/// <summary>");
            WriteLine("/// Writes the given <see cref=\"{0}\"/> to an <see cref=\"Ibasa.IO.BinaryWriter\">.", Name);
            WriteLine("/// </summary>");
            WriteLine("public static void Write(this Ibasa.IO.BinaryWriter writer, {0} quaternion)", Name);
            WriteLine("{");
            Indent();
            foreach(var component in Components)
            {
                WriteLine("writer.Write(quaternion.{0});", component);
            }
            Dedent();
            WriteLine("}");
            WriteLine("/// <summary>");
            WriteLine("/// Reads a <see cref=\"{0}\"/> from an <see cref=\"Ibasa.IO.BinaryReader\">.", Name);
            WriteLine("/// </summary>");
            WriteLine("public static {0} Read{0}(this Ibasa.IO.BinaryReader reader)", Name);
            WriteLine("{");
            Indent();
            WriteLine("return new {0}({1});", Name, string.Join(", ", Components.Select(c => string.Format("reader.Read{0}()", Type.CLRName))));
            Dedent();
            WriteLine("}");
            WriteLine("#endregion");
            #endregion

            #region Operations
            WriteLine("#region Operations");
            if (Type.NegativeType != NumberType.Invalid)
            {
                var negQuaternion = new Quaternion(Type.NegativeType);

                WriteLine("/// <summary>");
                WriteLine("/// Returns the additive inverse of a quaternion.");
                WriteLine("/// </summary>");
                WriteLine("/// <param name=\"value\">A quaternion.</param>");
                WriteLine("/// <returns>The negative of value.</returns>");
                WriteLine("public static {0} Negative({1} value)", negQuaternion, Name);
                WriteLine("{");
                Indent();
                WriteLine("return new {0}({1});", negQuaternion,
                    string.Join(", ", Components.Select(component => "-value." + component)));
                Dedent();
                WriteLine("}");
            }

            WriteLine("/// <summary>");
            WriteLine("/// Adds two quaternions and returns the result.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"left\">The first value to add.</param>");
            WriteLine("/// <param name=\"right\">The second value to add.</param>");
            WriteLine("/// <returns>The sum of left and right.</returns>");
            WriteLine("public static {0} Add({1} left, {1} right)", result, Name);
            WriteLine("{");
            Indent();
            WriteLine("return new {0}({1});", result,
                string.Join(", ", Components.Select(component => string.Format("left.{0} + right.{0}", component))));
            Dedent();
            WriteLine("}");

            WriteLine("/// <summary>");
            WriteLine("/// Subtracts one quaternion from another and returns the result.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"left\">The value to subtract from (the minuend).</param>");
            WriteLine("/// <param name=\"right\">The value to subtract (the subtrahend).</param>");
            WriteLine("/// <returns>The result of subtracting right from left (the difference).</returns>");
            WriteLine("public static {0} Subtract({1} left, {1} right)", result, Name);
            WriteLine("{");
            Indent();
            WriteLine("return new {0}({1});", result,
                string.Join(", ", Components.Select(component => string.Format("left.{0} - right.{0}", component))));
            Dedent();
            WriteLine("}");

            WriteLine("/// <summary>");
            WriteLine("/// Returns the product of two quaternions.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"left\">The first value to add.</param>");
            WriteLine("/// <param name=\"right\">The second value to add.</param>");
            WriteLine("/// <returns>The product of the left and right parameters.</returns>");
            WriteLine("public static {0} Multiply({1} left, {1} right)", result, Name);
            WriteLine("{");
            Indent();
            WriteLine("return new {0}(", Name);
            WriteLine("\t(left.A * right.A) - ((left.B * right.B) + (left.C * right.C) + (left.D * right.D)),");
            WriteLine("\t(left.A * right.B) + (left.B * right.A) + (left.D * right.C) - (left.C * right.D),");
            WriteLine("\t(left.A * right.C) + (left.C * right.A) + (left.B * right.D) - (left.D * right.B),");
            WriteLine("\t(left.A * right.D) + (left.D * right.A) + (left.C * right.B) - (left.B * right.C));");
            Dedent();
            WriteLine("}");

            WriteLine("/// <summary>");
            WriteLine("/// Divides one quaternion by another and returns the result.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"left\">The quaternion to be divided (the dividend).</param>");
            WriteLine("/// <param name=\"right\">The quaternion to divide by (the divisor).</param>");
            WriteLine("/// <returns>The result of dividing left by right (the quotient).</returns>");
            WriteLine("public static {0} Divide({1} left, {1} right)", result, Name);
            WriteLine("{");
            Indent();
            WriteLine("return new {0}(", Name);
            WriteLine("\t(left.A * right.A) - ((left.B * -right.B) + (left.C * -right.C) + (left.D * -right.D)) / AbsoluteSquared(right),");
            WriteLine("\t((left.A * -right.B) + (left.B * right.A) + (left.D * -right.C) - (left.C * -right.D)) / AbsoluteSquared(right),");
            WriteLine("\t((left.A * -right.C) + (left.C * right.A) + (left.B * -right.D) - (left.D * -right.B)) / AbsoluteSquared(right),");
            WriteLine("\t((left.A * -right.D) + (left.D * right.A) + (left.C * -right.B) - (left.B * -right.C)) / AbsoluteSquared(right));");
            Dedent();
            WriteLine("}");
            WriteLine("#endregion");
            #endregion

            #region Equatable
            WriteLine("#region Equatable");
            WriteLine("/// <summary>");
            WriteLine("/// Returns a value that indicates whether two quaternions are equal.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"left\">The first quaternion to compare.</param>");
            WriteLine("/// <param name=\"right\">The second quaternion to compare.</param>");
            WriteLine("/// <returns>true if the left and right are equal; otherwise, false.</returns>");
            WriteLine("public static bool Equals({0} left, {0} right)", Name);
            WriteLine("{");
            Indent();
            WriteLine("return left == right;");
            Dedent();
            WriteLine("}");
            WriteLine("#endregion");
            #endregion

            #region Test
            WriteLine("#region Test");
            WriteLine("/// <summary>");
            WriteLine("/// Determines whether all components of a quaternion are non-zero.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"value\">A quaternion.</param>");
            WriteLine("/// <returns>true if all components are non-zero; false otherwise.</returns>");
            if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
            WriteLine("public static bool All({0} value)", Name);
            WriteLine("{");
            Indent();
            WriteLine("return {0};",
                string.Join(" && ", Components.Select(component => string.Format("value.{0} != 0", component))));
            Dedent();
            WriteLine("}");
            WriteLine("/// <summary>");
            WriteLine("/// Determines whether all components of a quaternion satisfy a condition.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"value\">A quaternion.</param>");
            WriteLine("/// <param name=\"predicate\">A function to test each component for a condition.</param>");
            WriteLine("/// <returns>true if every component of the quaternion passes the test in the specified");
            WriteLine("/// predicate; otherwise, false.</returns>");
            if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
            WriteLine("public static bool All({0} value, Predicate<{1}> predicate)", Name, Type);
            WriteLine("{");
            Indent();
            WriteLine("return {0};",
                string.Join(" && ", Components.Select(component => string.Format("predicate(value.{0})", component))));
            Dedent();
            WriteLine("}");
            WriteLine("/// <summary>");
            WriteLine("/// Determines whether any component of a quaternion is non-zero.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"value\">A quaternion.</param>");
            WriteLine("/// <returns>true if any components are non-zero; false otherwise.</returns>");
            if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
            WriteLine("public static bool Any({0} value)", Name);
            WriteLine("{");
            Indent();
            WriteLine("return {0};",
                string.Join(" || ", Components.Select(component => string.Format("value.{0} != 0", component))));
            Dedent();
            WriteLine("}");
            WriteLine("/// <summary>");
            WriteLine("/// Determines whether any components of a quaternion satisfy a condition.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"value\">A quaternion.</param>");
            WriteLine("/// <param name=\"predicate\">A function to test each component for a condition.</param>");
            WriteLine("/// <returns>true if any component of the quaternion passes the test in the specified");
            WriteLine("/// predicate; otherwise, false.</returns>");
            if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
            WriteLine("public static bool Any({0} value, Predicate<{1}> predicate)", Name, Type);
            WriteLine("{");
            Indent();
            WriteLine("return {0};",
                string.Join(" || ", Components.Select(component => string.Format("predicate(value.{0})", component))));
            Dedent();
            WriteLine("}");
            WriteLine("#endregion");
            #endregion

            #region Properties
            
            WriteLine("#region Properties");

            WriteLine("/// <summary>");
            WriteLine("/// Return the axis angle representation of a unit quaternion.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"value\">A unit quaternion.</param>");
            WriteLine("/// <returns>The axis angle of a quaternion.</returns>");
            WriteLine("public static Tuple<{0}, {1}> AxisAngle({2} value)", new Vector(Type, 3), Type, Name);
            WriteLine("{");
            Indent();
            WriteLine("var s = Functions.Sqrt(1 - value.A - value.A);");
            WriteLine("return Tuple.Create(");
            WriteLine("\tnew {0}(value.B / s, value.C / s, value.D / s),", new Vector(Type, 3));
            WriteLine("\t2 * Functions.Acos(value.A));");
            Dedent();
            WriteLine("}");

            WriteLine("/// <summary>");
            WriteLine("/// Return real part of a quaternion.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"value\">A quaternion.</param>");
            WriteLine("/// <returns>The real part of a quaternion.</returns>");
            WriteLine("public static {0} Real({0} value)", Name);
            WriteLine("{");
            Indent();
            WriteLine("return new {0}(value.A, 0, 0, 0);", Name);
            Dedent();
            WriteLine("}");
            WriteLine("/// <summary>");
            WriteLine("/// Return imaginary part of a quaternion.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"value\">A quaternion.</param>");
            WriteLine("/// <returns>The imaginary part of a quaternion.</returns>");
            WriteLine("public static {0} Imaginary({0} value)", Name);
            WriteLine("{");
            Indent();
            WriteLine("return new {0}(0, value.B, value.C, value.D);", Name);
            Dedent();
            WriteLine("}");
            WriteLine("/// <summary>");
            WriteLine("/// Computes the absolute squared value of a quaternion and returns the result.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"value\">A quaternion.</param>");
            WriteLine("/// <returns>The absolute squared value of value.</returns>");
            WriteLine("public static {0} AbsoluteSquared({1} value)", Type.PositiveType, Name);
            WriteLine("{");
            Indent();
            WriteLine("return (value.A * value.A + value.B * value.B + value.C * value.C + value.D * value.D);");
            Dedent();
            WriteLine("}");
            WriteLine("/// <summary>");
            WriteLine("/// Computes the absolute value (or modulus or magnitude) of a quaternion and returns the result.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"value\">A quaternion.</param>");
            WriteLine("/// <returns>The absolute value of value.</returns>");
            WriteLine("public static {0} Absolute({1} value)", Type.RealType, Name);
            WriteLine("{");
            Indent();
            WriteLine("return Functions.Sqrt(value.A * value.A + value.B * value.B + value.C * value.C + value.D * value.D);");
            Dedent();
            WriteLine("}");
            WriteLine("/// <summary>");
            WriteLine("/// Computes the normalized value (or unit) of a quaternion.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"value\">A quaternion.</param>");
            WriteLine("/// <returns>The normalized value of value.</returns>");
            WriteLine("public static {0} Normalize({0} value)", Name);
            WriteLine("{");
            Indent();
            WriteLine("var absolute = Absolute(value);");
            WriteLine("if(absolute <= {0}.Epsilon)", Type.RealType);
            WriteLine("{");
            Indent();
            WriteLine("return {0}.Zero;", Name);
            Dedent();
            WriteLine("}");
            WriteLine("return value / absolute;");
            Dedent();
            WriteLine("}");
            WriteLine("/// <summary>");
            WriteLine("/// Returns the multiplicative inverse of a quaternion.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"value\">A quaternion.</param>");
            WriteLine("/// <returns>The reciprocal of value.</returns>");
            WriteLine("public static {0} Reciprocal({0} value)", Name);
            WriteLine("{");
            Indent();
            WriteLine("var absoluteSquared = AbsoluteSquared(value);");
            WriteLine("return new {0}(", Name);
            WriteLine("\tvalue.A / absoluteSquared,");
            WriteLine("\t-value.B / absoluteSquared,");
            WriteLine("\t-value.C / absoluteSquared,");
            WriteLine("\t-value.D / absoluteSquared);");
            Dedent();
            WriteLine("}");
            WriteLine("/// <summary>");
            WriteLine("/// Computes the conjugate of a quaternion and returns the result.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"value\">A quaternion.</param>");
            WriteLine("/// <returns>The conjugate of value.</returns>");
            WriteLine("public static {0} Conjugate({0} value)", Name);
            WriteLine("{");
            Indent();
            WriteLine("return new {0}(value.A, -value.B, -value.C, -value.D);", Name);
            Dedent();
            WriteLine("}");
            WriteLine("/// <summary>");
            WriteLine("/// Computes the argument of a quaternion and returns the result.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"value\">A quaternion.</param>");
            WriteLine("/// <returns>The argument of value.</returns>");
            WriteLine("public static {0} Argument({1} value)", Type.RealType, Name);
            WriteLine("{");
            Indent();
            WriteLine("return Functions.Atan2(Absolute(Imaginary(value)), value.A);");
            Dedent();
            WriteLine("}");
            WriteLine("#endregion");
            #endregion
            
            #region Product
            WriteLine("#region Product");
            WriteLine("/// <summary>");
            WriteLine("/// Calculates the dot product (inner product) of two quaternions.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"left\">First source quaternion.</param>");
            WriteLine("/// <param name=\"right\">Second source quaternion.</param>");
            WriteLine("/// <returns>The dot product of the two quaternions.</returns>");
            WriteLine("public static {0} Dot({1} left, {1} right)", Type, Name);
            Indent("{");
            WriteLine("return left.A * right.A + left.B * right.B + left.C * right.C + left.D * right.D;");
            Dedent("}");
            WriteLine("#endregion");
            #endregion

            #region Interpolation
            WriteLine("#region Interpolation");
            WriteLine("/// <summary>");
            WriteLine("/// Performs a linear interpolation between two quaternions.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"start\">Start quaternion.</param>");
            WriteLine("/// <param name=\"end\">End quaternion.</param>");
            WriteLine("/// <param name=\"amount\">Value between 0 and 1 indicating the weight of <paramref name=\"end\"/>.</param>");
            WriteLine("/// <returns>The linear interpolation of the two quaternions.</returns>");
            WriteLine("/// <remarks>");
            WriteLine("/// This method performs the linear interpolation based on the following formula.");
            WriteLine("/// <code>start + (end - start) * amount</code>");
            WriteLine("/// Passing <paramref name=\"amount\"/> a value of 0 will cause <paramref name=\"start\"/> to be returned; a value of 1 will cause <paramref name=\"end\"/> to be returned. ");
            WriteLine("/// </remarks>");
            WriteLine("public static {0} Lerp({0} start, {0} end, {1} amount)", Name, Type);
            Indent("{");
            WriteLine("return new {0}(", Name);
            WriteLine("\tFunctions.Lerp(start.A, end.A, amount),");
            WriteLine("\tFunctions.Lerp(start.B, end.B, amount),");
            WriteLine("\tFunctions.Lerp(start.C, end.C, amount),");
            WriteLine("\tFunctions.Lerp(start.D, end.D, amount));");
            Dedent("}");
            WriteLine("/// <summary>");
            WriteLine("/// Interpolates between two unit quaternions, using spherical linear interpolation.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"start\">Start quaternion.</param>");
            WriteLine("/// <param name=\"end\">End quaternion.</param>");
            WriteLine("/// <param name=\"amount\">Value between 0 and 1 indicating the weight of <paramref name=\"end\"/>.</param>");
            WriteLine("/// <returns>The spherical linear interpolation of the two quaternions.</returns>");
            WriteLine("///  <remarks>");
            WriteLine("/// Passing <paramref name=\"amount\"/> a value of 0 will cause <paramref name=\"start\"/> to be returned; a value of 1 will cause <paramref name=\"end\"/> to be returned. ");
            WriteLine("/// </remarks>");
            WriteLine("public static {0} Slerp({0} start, {0} end, {1} amount)", Name, Type);
            Indent("{");
            WriteLine("var cosTheta = Dot(start, end);");
            WriteLine("//Cannot use slerp, use lerp instead");
            WriteLine("if (Functions.Abs(cosTheta) - 1 < {0}.Epsilon)", Type);
            Indent("{");
            WriteLine("return Lerp(start, end, amount);");
            Dedent("}");
            WriteLine("var theta = Functions.Acos(cosTheta);");
            WriteLine("var sinTheta = Functions.Sin(theta);");
            WriteLine("var t0 = Functions.Sin((1 - amount) * theta) / sinTheta;");
            WriteLine("var t1 = Functions.Sin(amount * theta) / sinTheta;");
            WriteLine("return t0 * start + t1 * end;");
            Dedent("}");
            WriteLine("#endregion");
            #endregion

            #region Transform
            WriteLine("#region Transform");

            var vector4 = new Vector(Type, 4);

            WriteLine("public static {0} Transform({0} vector, {1} rotation)", vector4, Name);
            Indent("{");
            WriteLine("var v = rotation * new {0}(vector.X, vector.Y, vector.Z, 0) * Conjugate(rotation);", Name);
            WriteLine("return new {0}(v.A, v.B, v.C, vector.W);", vector4);
            Dedent("}");
            
            var vector3 = new Vector(Type, 3);

            WriteLine("public static {0} Transform({0} vector, {1} rotation)", vector3, Name);
            Indent("{");
            WriteLine("var v = rotation * new {0}(vector.X, vector.Y, vector.Z, 0) * Conjugate(rotation);", Name);
            WriteLine("return new {0}(v.A, v.B, v.C);", vector3);
            Dedent("}");

            WriteLine("#endregion");
            #endregion

            #region Old
            //#region Per component
            //WriteLine("#region Per component");

            //WriteLine("#region Transform");
            //foreach (var type in Types)
            //{
            //    var transform = new Quaternion(type, Dimension);

            //    WriteLine("/// <summary>");
            //    WriteLine("/// Transforms the components of a quaternion and returns the result.");
            //    WriteLine("/// </summary>");
            //    WriteLine("/// <param name=\"value\">The quaternion to transform.</param>");
            //    WriteLine("/// <param name=\"transformer\">A transform function to apply to each component.</param>");
            //    WriteLine("/// <returns>The result of transforming each component of value.</returns>");
            //    if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
            //    WriteLine("public static {0} Transform({1} value, Func<{2}, {3}> transformer)", transform, Name, Type, transform.Type);
            //    WriteLine("{");
            //    Indent();
            //    WriteLine("return new {0}({1});", transform,
            //        string.Join(", ", Components.Select(component => string.Format("transformer(value.{0})", component))));
            //    Dedent();
            //    WriteLine("}");
            //}
            //WriteLine("#endregion");

            //WriteLine("/// <summary>");
            //WriteLine("/// Multiplys the components of two quaternions and returns the result.");
            //WriteLine("/// </summary>");
            //WriteLine("/// <param name=\"left\">The first quaternion to modulate.</param>");
            //WriteLine("/// <param name=\"right\">The second quaternion to modulate.</param>");
            //WriteLine("/// <returns>The result of multiplying each component of left by the matching component in right.</returns>");
            //if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
            //WriteLine("public static {0} Modulate({1} left, {1} right)", result, Name);
            //WriteLine("{");
            //Indent();
            //WriteLine("return new {0}({1});", result,
            //    string.Join(", ", Components.Select(component => string.Format("left.{0} * right.{0}", component))));
            //Dedent();
            //WriteLine("}");
            //WriteLine("/// <summary>");
            //WriteLine("/// Returns the absolute value (per component).");
            //WriteLine("/// </summary>");
            //WriteLine("/// <param name=\"value\">A quaternion.</param>");
            //WriteLine("/// <returns>The absolute value (per component) of value.</returns>");
            //if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
            //WriteLine("public static {0} Abs({0} value)", Name);
            //WriteLine("{");
            //Indent();
            //WriteLine("return new {0}({1});", Name,
            //    string.Join(", ", Components.Select(component => string.Format("Functions.Abs(value.{0})", component))));
            //Dedent();
            //WriteLine("}");
            //WriteLine("/// <summary>");
            //WriteLine("/// Returns a quaternion that contains the lowest value from each pair of components.");
            //WriteLine("/// </summary>");
            //WriteLine("/// <param name=\"value1\">The first quaternion.</param>");
            //WriteLine("/// <param name=\"value2\">The second quaternion.</param>");
            //WriteLine("/// <returns>The lowest of each component in left and the matching component in right.</returns>");
            //if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
            //WriteLine("public static {0} Min({0} value1, {0} value2)", Name);
            //WriteLine("{");
            //Indent();
            //WriteLine("return new {0}({1});", Name,
            //    string.Join(", ", Components.Select(component => string.Format("Functions.Min(value1.{0}, value2.{0})", component))));
            //Dedent();
            //WriteLine("}");
            //WriteLine("/// <summary>");
            //WriteLine("/// Returns a quaternion that contains the highest value from each pair of components.");
            //WriteLine("/// </summary>");
            //WriteLine("/// <param name=\"value1\">The first quaternion.</param>");
            //WriteLine("/// <param name=\"value2\">The second quaternion.</param>");
            //WriteLine("/// <returns>The highest of each component in left and the matching component in right.</returns>");
            //if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
            //WriteLine("public static {0} Max({0} value1, {0} value2)", Name);
            //WriteLine("{");
            //Indent();
            //WriteLine("return new {0}({1});", Name,
            //    string.Join(", ", Components.Select(component => string.Format("Functions.Max(value1.{0}, value2.{0})", component))));
            //Dedent();
            //WriteLine("}");
            //WriteLine("/// <summary>");
            //WriteLine("/// Constrains each component to a given range.");
            //WriteLine("/// </summary>");
            //WriteLine("/// <param name=\"value\">A quaternion to constrain.</param>");
            //WriteLine("/// <param name=\"min\">The minimum values for each component.</param>");
            //WriteLine("/// <param name=\"max\">The maximum values for each component.</param>");
            //WriteLine("/// <returns>A quaternion with each component constrained to the given range.</returns>");
            //if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
            //WriteLine("public static {0} Clamp({0} value, {0} min, {0} max)", Name);
            //WriteLine("{");
            //Indent();
            //WriteLine("return new {0}({1});", Name,
            //    string.Join(", ", Components.Select(component => string.Format("Functions.Clamp(value.{0}, min.{0}, max.{0})", component))));
            //Dedent();
            //WriteLine("}");
            //if (Type.IsReal)
            //{
            //    WriteLine("/// <summary>");
            //    WriteLine("/// Constrains each component to the range 0 to 1.");
            //    WriteLine("/// </summary>");
            //    WriteLine("/// <param name=\"value\">A quaternion to saturate.</param>");
            //    WriteLine("/// <returns>A quaternion with each component constrained to the range 0 to 1.</returns>");
            //    if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
            //    WriteLine("public static {0} Saturate({0} value)", Name);
            //    WriteLine("{");
            //    Indent();
            //    WriteLine("return new {0}({1});", Name,
            //        string.Join(", ", Components.Select(component => string.Format("Functions.Saturate(value.{0})", component))));
            //    Dedent();
            //    WriteLine("}");
            //    WriteLine("/// <summary>");
            //    WriteLine("/// Returns a quaternion where each component is the smallest integral value that");
            //    WriteLine("/// is greater than or equal to the specified component.");
            //    WriteLine("/// </summary>");
            //    WriteLine("/// <param name=\"value\">A quaternion.</param>");
            //    WriteLine("/// <returns>The ceiling of value.</returns>");
            //    if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
            //    WriteLine("public static {0} Ceiling({1} value)", result, Name);
            //    WriteLine("{");
            //    Indent();
            //    WriteLine("return new {0}({1});", result,
            //        string.Join(", ", Components.Select(component => string.Format("Functions.Ceiling(value.{0})", component))));
            //    Dedent();
            //    WriteLine("}");
            //    WriteLine("/// <summary>");
            //    WriteLine("/// Returns a quaternion where each component is the largest integral value that");
            //    WriteLine("/// is less than or equal to the specified component.");
            //    WriteLine("/// </summary>");
            //    WriteLine("/// <param name=\"value\">A quaternion.</param>");
            //    WriteLine("/// <returns>The floor of value.</returns>");
            //    if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
            //    WriteLine("public static {0} Floor({1} value)", result, Name);
            //    WriteLine("{");
            //    Indent();
            //    WriteLine("return new {0}({1});", result,
            //        string.Join(", ", Components.Select(component => string.Format("Functions.Floor(value.{0})", component))));
            //    Dedent();
            //    WriteLine("}");
            //    WriteLine("/// <summary>");
            //    WriteLine("/// Returns a quaternion where each component is the integral part of the specified component.");
            //    WriteLine("/// </summary>");
            //    WriteLine("/// <param name=\"value\">A quaternion.</param>");
            //    WriteLine("/// <returns>The integral of value.</returns>");
            //    if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
            //    WriteLine("public static {0} Truncate({1} value)", result, Name);
            //    WriteLine("{");
            //    Indent();
            //    WriteLine("return new {0}({1});", result,
            //        string.Join(", ", Components.Select(component => string.Format("Functions.Truncate(value.{0})", component))));
            //    Dedent();
            //    WriteLine("}");
            //    WriteLine("/// <summary>");
            //    WriteLine("/// Returns a quaternion where each component is the fractional part of the specified component.");
            //    WriteLine("/// </summary>");
            //    WriteLine("/// <param name=\"value\">A quaternion.</param>");
            //    WriteLine("/// <returns>The fractional of value.</returns>");
            //    if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
            //    WriteLine("public static {0} Fractional({1} value)", result, Name);
            //    WriteLine("{");
            //    Indent();
            //    WriteLine("return new {0}({1});", result,
            //        string.Join(", ", Components.Select(component => string.Format("Functions.Fractional(value.{0})", component))));
            //    Dedent();
            //    WriteLine("}");
            //    WriteLine("/// <summary>");
            //    WriteLine("/// Returns a quaternion where each component is rounded to the nearest integral value.");
            //    WriteLine("/// </summary>");
            //    WriteLine("/// <param name=\"value\">A quaternion.</param>");
            //    WriteLine("/// <returns>The result of rounding value.</returns>");
            //    if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
            //    WriteLine("public static {0} Round({1} value)", result, Name);
            //    WriteLine("{");
            //    Indent();
            //    WriteLine("return new {0}({1});", result,
            //        string.Join(", ", Components.Select(component => string.Format("Functions.Round(value.{0})", component))));
            //    Dedent();
            //    WriteLine("}");
            //    WriteLine("/// <summary>");
            //    WriteLine("/// Returns a quaternion where each component is rounded to the nearest integral value.");
            //    WriteLine("/// </summary>");
            //    WriteLine("/// <param name=\"value\">A quaternion.</param>");
            //    WriteLine("/// <param name=\"digits\">The number of fractional digits in the return value.</param>");
            //    WriteLine("/// <returns>The result of rounding value.</returns>");
            //    if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
            //    WriteLine("public static {0} Round({1} value, int digits)", result, Name);
            //    WriteLine("{");
            //    Indent();
            //    WriteLine("return new {0}({1});", result,
            //        string.Join(", ", Components.Select(component => string.Format("Functions.Round(value.{0}, digits)", component))));
            //    Dedent();
            //    WriteLine("}");
            //    WriteLine("/// <summary>");
            //    WriteLine("/// Returns a quaternion where each component is rounded to the nearest integral value.");
            //    WriteLine("/// </summary>");
            //    WriteLine("/// <param name=\"value\">A quaternion.</param>");
            //    WriteLine("/// <param name=\"mode\">Specification for how to round value if it is midway between two other numbers.</param>");
            //    WriteLine("/// <returns>The result of rounding value.</returns>");
            //    if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
            //    WriteLine("public static {0} Round({1} value, MidpointRounding mode)", result, Name);
            //    WriteLine("{");
            //    Indent();
            //    WriteLine("return new {0}({1});", result,
            //        string.Join(", ", Components.Select(component => string.Format("Functions.Round(value.{0}, mode)", component))));
            //    Dedent();
            //    WriteLine("}");
            //    WriteLine("/// <summary>");
            //    WriteLine("/// Returns a quaternion where each component is rounded to the nearest integral value.");
            //    WriteLine("/// </summary>");
            //    WriteLine("/// <param name=\"value\">A quaternion.</param>");
            //    WriteLine("/// <param name=\"digits\">The number of fractional digits in the return value.</param>");
            //    WriteLine("/// <param name=\"mode\">Specification for how to round value if it is midway between two other numbers.</param>");
            //    WriteLine("/// <returns>The result of rounding value.</returns>");
            //    if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
            //    WriteLine("public static {0} Round({1} value, int digits, MidpointRounding mode)", result, Name);
            //    WriteLine("{");
            //    Indent();
            //    WriteLine("return new {0}({1});", result,
            //        string.Join(", ", Components.Select(component => string.Format("Functions.Round(value.{0}, digits, mode)", component))));
            //    Dedent();
            //    WriteLine("}");
            //    WriteLine("/// <summary>");
            //    WriteLine("/// Calculates the reciprocal of each component in the quaternion.");
            //    WriteLine("/// </summary>");
            //    WriteLine("/// <param name=\"value\">A quaternion.</param>");
            //    WriteLine("/// <returns>A quaternion with the reciprocal of each of values components.</returns>");
            //    if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
            //    WriteLine("public static {0} Reciprocal({1} value)", result, Name);
            //    WriteLine("{");
            //    Indent();
            //    WriteLine("return new {0}({1});", result,
            //        string.Join(", ", Components.Select(component => string.Format("1 / value.{0}", component))));
            //    Dedent();
            //    WriteLine("}");
            //}
            //WriteLine("#endregion");
            //#endregion

            //#region Barycentric, Reflect, Refract
            //if (Type.IsReal)
            //{
            //    WriteLine("#region Barycentric, Reflect, Refract");
            //    WriteLine("/// <summary>");
            //    WriteLine("/// Returns the Cartesian coordinate for one axis of a point that is defined");
            //    WriteLine("/// by a given triangle and two normalized barycentric (areal) coordinates.");
            //    WriteLine("/// </summary>");
            //    WriteLine("/// <param name=\"value1\">The coordinate of vertex 1 of the defining triangle.</param>");
            //    WriteLine("/// <param name=\"value2\">The coordinate of vertex 2 of the defining triangle.</param>");
            //    WriteLine("/// <param name=\"value3\">The coordinate of vertex 3 of the defining triangle.</param>");
            //    WriteLine("/// <param name=\"amount1\">The normalized barycentric (areal) coordinate b2, equal to the weighting");
            //    WriteLine("/// factor for vertex 2, the coordinate of which is specified in value2.</param>");
            //    WriteLine("/// <param name=\"amount2\">The normalized barycentric (areal) coordinate b3, equal to the weighting");
            //    WriteLine("/// factor for vertex 3, the coordinate of which is specified in value3.</param>");
            //    WriteLine("/// <returns>Cartesian coordinate of the specified point.</returns>");
            //    if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
            //    WriteLine("public static {0} Barycentric({1} value1, {1} value2, {1} value3, {2} amount1, {2} amount2)", result, Name, result.Type);
            //    WriteLine("{");
            //    Indent();
            //    WriteLine("return ((1 - amount1 - amount2) * value1) + (amount1 * value2) + (amount2 * value3);");
            //    Dedent();
            //    WriteLine("}");
            //    WriteLine("/// <summary>");
            //    WriteLine("/// Returns the reflection of a quaternion off a surface that has the specified normal.");
            //    WriteLine("/// </summary>");
            //    WriteLine("/// <param name=\"quaternion\">The source quaternion.</param>");
            //    WriteLine("/// <param name=\"normal\">Normal of the surface.</param>");
            //    WriteLine("/// <returns>The reflected quaternion.</returns>");
            //    WriteLine("/// <remarks>Reflect only gives the direction of a reflection off a surface, it does not determine");
            //    WriteLine("/// whether the original quaternion was close enough to the surface to hit it.</remarks>");
            //    if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
            //    WriteLine("public static {0} Reflect({1} quaternion, {1} normal)", result, Name);
            //    WriteLine("{");
            //    Indent();
            //    WriteLine("return quaternion - ((2 * Dot(quaternion, normal)) * normal);");
            //    Dedent();
            //    WriteLine("}");
            //    WriteLine("/// <summary>");
            //    WriteLine("/// Returns the refraction of a quaternion off a surface that has the specified normal, and refractive index.");
            //    WriteLine("/// </summary>");
            //    WriteLine("/// <param name=\"quaternion\">The source quaternion.</param>");
            //    WriteLine("/// <param name=\"normal\">Normal of the surface.</param>");
            //    WriteLine("/// <param name=\"index\">The refractive index, destination index over source index.</param>");
            //    WriteLine("/// <returns>The refracted quaternion.</returns>");
            //    WriteLine("/// <remarks>Refract only gives the direction of a refraction off a surface, it does not determine");
            //    WriteLine("/// whether the original quaternion was close enough to the surface to hit it.</remarks>");
            //    if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
            //    WriteLine("public static {0} Refract({1} quaternion, {1} normal, {2} index)", result, Name, result.Type);
            //    WriteLine("{");
            //    Indent();
            //    WriteLine("var cos1 = Dot(quaternion, normal);");
            //    WriteLine("var radicand = 1 - (index * index) * (1 - (cos1 * cos1));");
            //    WriteLine("if (radicand < 0)");
            //    WriteLine("{");
            //    Indent();
            //    WriteLine("return {0}.Zero;", result);
            //    Dedent();
            //    WriteLine("}");
            //    WriteLine("return (index * quaternion) + ((Functions.Sqrt(radicand) - index * cos1) * normal);");
            //    Dedent();
            //    WriteLine("}");
            //    WriteLine("#endregion");
            //}
            //#endregion

            //#region Interpolation
            //if (Type.IsReal)
            //{
            //    WriteLine("#region Interpolation");
            //    //WriteLine("/// <summary>");
            //    //WriteLine("/// Performs a Hermite spline interpolation.");
            //    //WriteLine("/// </summary>");
            //    //WriteLine("/// <param name=\"value1\">First source position.</param>");
            //    //WriteLine("/// <param name=\"tangent1\">First source tangent.</param>");
            //    //WriteLine("/// <param name=\"value2\">Second source position.</param>");
            //    //WriteLine("/// <param name=\"tangent2\">Second source tangent.</param>");
            //    //WriteLine("/// <param name=\"amount\">Weighting factor.</param>");
            //    //WriteLine("/// <returns>The result of the Hermite spline interpolation.</returns>");
            //    //if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); } 
            //    //WriteLine("public static {0} Hermite({1} value1, {1} tangent1, {1} value2, {1} tangent2, {2} amount)", result, Name, result.Type);
            //    //WriteLine("{");
            //    //Indent();
            //    //WriteLine("var amount2 = amount * amount;");
            //    //WriteLine("var amount3 = amount2 * amount;");
            //    //WriteLine("var h00 = 2 * amount3 - 3 * amount2 + 1;");
            //    //WriteLine("var h10 = amount3 - 2 * amount2 + amount;");
            //    //WriteLine("var h01 = -2 * amount3 + 3 * amount2;");
            //    //WriteLine("var h11 = amount3 - amount2;");
            //    //WriteLine("return h00 * value1 + h10 * tangent1 + h01 * value2 + h11 * tangent2;");
            //    //Dedent();
            //    //WriteLine("}");
            //    //WriteLine("/// <summary>");
            //    //WriteLine("/// Performs a Catmull-Rom interpolation using the specified positions.");
            //    //WriteLine("/// </summary>");
            //    //WriteLine("/// <param name=\"value1\">The first position in the interpolation.</param>");
            //    //WriteLine("/// <param name=\"value2\">The second position in the interpolation.</param>");
            //    //WriteLine("/// <param name=\"value3\">The third position in the interpolation.</param>");
            //    //WriteLine("/// <param name=\"value4\">The fourth position in the interpolation.</param>");
            //    //WriteLine("/// <param name=\"amount\">Weighting factor.</param>");
            //    //WriteLine("/// <returns>A quaternion that is the result of the Catmull-Rom interpolation.</returns>");
            //    //if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
            //    //WriteLine("public static {0} CatmullRom({1} value1, {1} value2, {1} value3, {1} value4, {2} amount)", result, Name, result.Type);
            //    //WriteLine("{");
            //    //Indent();
            //    //WriteLine("var tangent0 = (value3 - value1) / 2;");
            //    //WriteLine("var tangent1 = (value4 - value2) / 2;");
            //    //WriteLine("return Hermite(value2, tangent0, value3, tangent1, amount);");
            //    //Dedent();
            //    //WriteLine("}");
            //    //WriteLine("/// <summary>");
            //    //WriteLine("/// Performs a cubic interpolation between two values.");
            //    //WriteLine("/// </summary>");
            //    //WriteLine("/// <param name=\"value1\">First values.</param>");
            //    //WriteLine("/// <param name=\"value2\">Second values.</param>");
            //    //WriteLine("/// <param name=\"amount\">Value between 0 and 1 indicating the weight of <paramref name=\"value2\"/>.</param>");
            //    //WriteLine("/// <returns>The cubic interpolation of the two quaternions.</returns>");
            //    //if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
            //    //WriteLine("public static {0} SmoothStep({1} value1, {1} value2, {2} amount)", result, Name, result.Type);
            //    //WriteLine("{");
            //    //Indent();
            //    //WriteLine("amount = Functions.Saturate(amount);");
            //    //WriteLine("amount = amount * amount * (3 - 2 * amount);");
            //    //WriteLine("return Lerp(value1, value2, amount);");
            //    //Dedent();
            //    //WriteLine("}");
            //    WriteLine("/// <summary>");
            //    WriteLine("/// Performs a linear interpolation between two values.");
            //    WriteLine("/// </summary>");
            //    WriteLine("/// <param name=\"value1\">First value.</param>");
            //    WriteLine("/// <param name=\"value2\">Second value.</param>");
            //    WriteLine("/// <param name=\"amount\">Value between 0 and 1 indicating the weight of <paramref name=\"value2\"/>.</param>");
            //    WriteLine("/// <returns>The linear interpolation of the two values.</returns>");
            //    if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
            //    WriteLine("public static {0} Lerp({1} value1, {1} value2, {2} amount)", result, Name, result.Type);
            //    WriteLine("{");
            //    Indent();
            //    WriteLine("return (1 - amount) * value1 + amount * value2;");
            //    Dedent();
            //    WriteLine("}");
            //    //WriteLine("/// <summary>");
            //    //WriteLine("/// Performs a quadratic interpolation between three values.");
            //    //WriteLine("/// </summary>");
            //    //WriteLine("/// <param name=\"value1\">First value.</param>");
            //    //WriteLine("/// <param name=\"value2\">Second value.</param>");
            //    //WriteLine("/// <param name=\"value3\">Third value.</param>");
            //    //WriteLine("/// <param name=\"amount\">Value between 0 and 1 indicating the weight towards <paramref name=\"value3\"/>.</param>");
            //    //WriteLine("/// <returns>The quadratic interpolation of the three values.</returns>");
            //    //if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
            //    //WriteLine("public static {0} Qerp({1} value1, {1} value2, {1} value3, {2} amount)", result, Name, result.Type);
            //    //WriteLine("{");
            //    //Indent();
            //    //WriteLine("var p = 2 * value1 - value2 + 2 * value3;");
            //    //WriteLine("var q = value2 - value3 - 3 * value1;");
            //    //WriteLine("var r = value1;");
            //    //WriteLine("var amount2 = amount * amount;");
            //    //WriteLine("return (p * amount * amount2) + (q * amount) + (r);");
            //    //Dedent();
            //    //WriteLine("}");
            //    //WriteLine("/// <summary>");
            //    //WriteLine("/// Performs a cubic interpolation between four values.");
            //    //WriteLine("/// </summary>");
            //    //WriteLine("/// <param name=\"value1\">First value.</param>");
            //    //WriteLine("/// <param name=\"value2\">Second value.</param>");
            //    //WriteLine("/// <param name=\"value3\">Third value.</param>");
            //    //WriteLine("/// <param name=\"value4\">Fourth value.</param>");
            //    //WriteLine("/// <param name=\"amount\">Value between 0 and 1 indicating the weight towards <paramref name=\"value4\"/>.</param>");
            //    //WriteLine("/// <returns>The cubic interpolation of the four values.</returns>");
            //    //if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
            //    //WriteLine("public static {0} Cerp({1} value1, {1} value2, {1} value3, {1} value4, {2} amount)", result, Name, result.Type);
            //    //WriteLine("{");
            //    //Indent();
            //    //WriteLine("var p = (value4 - value3) - (value1 - value2);");
            //    //WriteLine("var q = (value1 - value2) - p;");
            //    //WriteLine("var r = value3 - value1;");
            //    //WriteLine("var s = value2;");
            //    //WriteLine("var amount2 = amount * amount;");
            //    //WriteLine("return (p * amount * amount2) + (q * amount2) + (r * amount) + (s);");
            //    //Dedent();
            //    //WriteLine("}");
            //    WriteLine("#endregion");
            //}
            //#endregion
            #endregion

            Dedent();
            WriteLine("}");
        }
예제 #10
0
파일: Point.cs 프로젝트: Frassle/Ibasa
        void Operations()
        {
            var result = new Point(Type.PositiveType, Dimension);
            var vector = new Vector(Type.PositiveType, Dimension);

            WriteLine("#region Operations");

            WriteLine("/// <summary>");
            WriteLine("/// Returns the identity of a specified point.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"value\">A point.</param>");
            WriteLine("/// <returns>The identity of value.</returns>");
            WriteLine("public static {0} operator +({1} value)", result, Name);
            WriteLine("{");
            Indent();
            WriteLine("return value;");
            Dedent();
            WriteLine("}");

            WriteLine("/// <summary>");
            WriteLine("/// Adds a point and a vector and returns the result.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"point\">The point value to add.</param>");
            WriteLine("/// <param name=\"vector\">The vector value to add.</param>");
            WriteLine("/// <returns>The sum of left and right.</returns>");
            WriteLine("public static {0} operator +({1} point, {2} vector)", result, Name, vector);
            WriteLine("{");
            Indent();
            WriteLine("return Point.Add(point, vector);");
            Dedent();
            WriteLine("}");

            WriteLine("/// <summary>");
            WriteLine("/// Adds a vector and a point and returns the result.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"vector\">The vector value to add.</param>");
            WriteLine("/// <param name=\"point\">The point value to add.</param>");
            WriteLine("/// <returns>The sum of left and right.</returns>");
            WriteLine("public static {0} operator +({1} vector, {2} point)", result, vector, Name);
            WriteLine("{");
            Indent();
            WriteLine("return Point.Add(point, vector);");
            Dedent();
            WriteLine("}");

            WriteLine("/// <summary>");
            WriteLine("/// Subtracts one point from another and returns the result.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"left\">The value to subtract from (the minuend).</param>");
            WriteLine("/// <param name=\"right\">The value to subtract (the subtrahend).</param>");
            WriteLine("/// <returns>The result of subtracting right from left (the difference).</returns>");
            WriteLine("public static {0} operator -({1} left, {1} right)", new Vector(result.Type, Dimension), Name);
            WriteLine("{");
            Indent();
            WriteLine("return Point.Subtract(left, right);");
            Dedent();
            WriteLine("}");

            WriteLine("/// <summary>");
            WriteLine("/// Subtracts a vector from a point and returns the result.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"point\">The point value to subtract from (the minuend).</param>");
            WriteLine("/// <param name=\"vector\">The vector value to subtract (the subtrahend).</param>");
            WriteLine("/// <returns>The result of subtracting vector from point (the difference).</returns>");
            WriteLine("public static {0} operator -({1} point, {2} vector)", result, Name, vector);
            WriteLine("{");
            Indent();
            WriteLine("return Point.Subtract(point, vector);");
            Dedent();
            WriteLine("}");

            WriteLine("/// <summary>");
            WriteLine("/// Returns the product of a point and scalar.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"left\">The point to multiply.</param>");
            WriteLine("/// <param name=\"right\">The scalar to multiply.</param>");
            WriteLine("/// <returns>The product of the left and right parameters.</returns>");
            WriteLine("public static {0} operator *({1} left, {2} right)", result, Name, result.Type);
            WriteLine("{");
            Indent();
            WriteLine("return Point.Multiply(left, right);");
            Dedent();
            WriteLine("}");

            WriteLine("/// <summary>");
            WriteLine("/// Returns the product of a scalar and point.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"left\">The scalar to multiply.</param>");
            WriteLine("/// <param name=\"right\">The point to multiply.</param>");
            WriteLine("/// <returns>The product of the left and right parameters.</returns>");
            WriteLine("public static {0} operator *({1} left, {2} right)", result, result.Type, Name);
            WriteLine("{");
            Indent();
            WriteLine("return Point.Multiply(right, left);");
            Dedent();
            WriteLine("}");

            WriteLine("/// <summary>");
            WriteLine("/// Divides a point by a scalar and returns the result.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"left\">The point to be divided (the dividend).</param>");
            WriteLine("/// <param name=\"right\">The scalar to divide by (the divisor).</param>");
            WriteLine("/// <returns>The result of dividing left by right (the quotient).</returns>");
            WriteLine("public static {0} operator /({1} left, {2} right)", result, Name, result.Type);
            WriteLine("{");
            Indent();
            WriteLine("return Point.Divide(left, right);");
            Dedent();
            WriteLine("}");

            WriteLine("#endregion");
        }
예제 #11
0
파일: Matrix.cs 프로젝트: Frassle/Ibasa
        private void Functions()
        {
            WriteLine("/// <summary>");
            WriteLine("/// Provides static methods for matrix functions.");
            WriteLine("/// </summary>");
            WriteLine("public static partial class Matrix");
            WriteLine("{");
            Indent();

            #region Operations
            WriteLine("#region Operations");
            WriteLine("public static {0} Negate({0} value)", Name);
            WriteLine("{");
            Indent();
            WriteLine("return new {0}({1});", Name, string.Join(", ", Elements.Select(element => string.Format("-value.{0}", element))));
            Dedent();
            WriteLine("}");

            WriteLine("public static {0} Add({0} left, {0} right)", Name);
            WriteLine("{");
            Indent();
            WriteLine("return new {0}({1});", Name, string.Join(", ", Elements.Select(element => string.Format("left.{0} + right.{0}", element))));
            Dedent();
            WriteLine("}");

            WriteLine("public static {0} Subtract({0} left, {0} right)", Name);
            WriteLine("{");
            Indent();
            WriteLine("return new {0}({1});", Name, string.Join(", ", Elements.Select(element => string.Format("left.{0} - right.{0}", element))));
            Dedent();
            WriteLine("}");

            foreach (var size in Matrix.Sizes)
            {
                var other = new Matrix(Type, Columns, size);
                var result = new Matrix(Type, Rows, size);

                WriteLine("public static {2} Multiply({0} left, {1} right)", Name, other, result);
                WriteLine("{");
                Indent();
                WriteLine("return new {0}({1});", result, string.Join(", ",
                    result.Elements.Select(element => string.Join(" + ", Enumerable.Range(0, Columns).Select(k =>
                        string.Format("left.M{0}{1} * right.M{2}{3}", 
                        element.Row + 1, k + 1, k + 1, element.Column + 1))))));
                Dedent();
                WriteLine("}");
            }

            WriteLine("public static {0} Multiply({0} matrix, {1} scalar)", Name, Type);
            WriteLine("{");
            Indent();
            WriteLine("return new {0}({1});", Name, string.Join(", ", Elements.Select(element => string.Format("matrix.{0} * scalar", element))));
            Dedent();
            WriteLine("}");

            WriteLine("public static {0} Divide({0} matrix, {1} scalar)", Name, Type);
            WriteLine("{");
            Indent();
            WriteLine("return new {0}({1});", Name, string.Join(", ", Elements.Select(element => string.Format("matrix.{0} / scalar", element))));
            Dedent();
            WriteLine("}");
            WriteLine("#endregion");
            #endregion

            #region Test
            WriteLine("#region Test");
            WriteLine("/// <summary>");
            WriteLine("/// Determines whether all elements of a matrix are non-zero.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"value\">A matrix.</param>");
            WriteLine("/// <returns>true if all elements are non-zero; false otherwise.</returns>");
            if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
            WriteLine("public static bool All({0} value)", Name);
            WriteLine("{");
            Indent();
            WriteLine("return {0};",
                string.Join(" && ", Elements.Select(element => string.Format("value.{0} != 0", element))));
            Dedent();
            WriteLine("}");
            WriteLine("/// <summary>");
            WriteLine("/// Determines whether all elements of a matrix satisfy a condition.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"value\">A matrix.</param>");
            WriteLine("/// <param name=\"predicate\">A function to test each element for a condition.</param>");
            WriteLine("/// <returns>true if every element of the matrix passes the test in the specified");
            WriteLine("/// predicate; otherwise, false.</returns>");
            if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
            WriteLine("public static bool All({0} value, Predicate<{1}> predicate)", Name, Type);
            WriteLine("{");
            Indent();
            WriteLine("return {0};",
                string.Join(" && ", Elements.Select(element => string.Format("predicate(value.{0})", element))));
            Dedent();
            WriteLine("}");
            WriteLine("/// <summary>");
            WriteLine("/// Determines whether any element of a matrix is non-zero.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"value\">A vector.</param>");
            WriteLine("/// <returns>true if any elements are non-zero; false otherwise.</returns>");
            if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
            WriteLine("public static bool Any({0} value)", Name);
            WriteLine("{");
            Indent();
            WriteLine("return {0};",
                string.Join(" || ", Elements.Select(element => string.Format("value.{0} != 0", element))));
            Dedent();
            WriteLine("}");
            WriteLine("/// <summary>");
            WriteLine("/// Determines whether any elements of a matrix satisfy a condition.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"value\">A vector.</param>");
            WriteLine("/// <param name=\"predicate\">A function to test each element for a condition.</param>");
            WriteLine("/// <returns>true if any element of the matrix passes the test in the specified");
            WriteLine("/// predicate; otherwise, false.</returns>");
            if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
            WriteLine("public static bool Any({0} value, Predicate<{1}> predicate)", Name, Type);
            WriteLine("{");
            Indent();
            WriteLine("return {0};",
                string.Join(" || ", Elements.Select(element => string.Format("predicate(value.{0})", element))));
            Dedent();
            WriteLine("}");
            WriteLine("#endregion");
            #endregion

            #region Per element
            WriteLine("#region Per element");

            WriteLine("#region Map");
            foreach (var type in Types)
            {
                var map = new Matrix(type, Rows, Columns);

                WriteLine("/// <summary>");
                WriteLine("/// Maps the elements of a matrix and returns the result.");
                WriteLine("/// </summary>");
                WriteLine("/// <param name=\"value\">The matrix to map.</param>");
                WriteLine("/// <param name=\"mapping\">A mapping function to apply to each element.</param>");
                WriteLine("/// <returns>The result of mapping each element of value.</returns>");
                if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
                WriteLine("public static {0} Map({1} value, Func<{2}, {3}> mapping)", map, Name, Type, map.Type);
                WriteLine("{");
                Indent();
                WriteLine("return new {0}({1});", map,
                    string.Join(", ", Elements.Select(element => string.Format("mapping(value.{0})", element))));
                Dedent();
                WriteLine("}");
            }
            WriteLine("#endregion");

            WriteLine("/// <summary>");
            WriteLine("/// Multiplys the elements of two matrices and returns the result.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"left\">The first matrix to modulate.</param>");
            WriteLine("/// <param name=\"right\">The second matrix to modulate.</param>");
            WriteLine("/// <returns>The result of multiplying each element of left by the matching element in right.</returns>");
            if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
            WriteLine("public static {0} Modulate({0} left, {0} right)", Name);
            WriteLine("{");
            Indent();
            WriteLine("return new {0}({1});", Name,
                string.Join(", ", Elements.Select(element => string.Format("left.{0} * right.{0}", element))));
            Dedent();
            WriteLine("}");
            WriteLine("/// <summary>");
            WriteLine("/// Returns the absolute value (per element).");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"value\">A matrix.</param>");
            WriteLine("/// <returns>The absolute value (per element) of value.</returns>");
            if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
            WriteLine("public static {0} Abs({0} value)", Name);
            WriteLine("{");
            Indent();
            WriteLine("return new {0}({1});", Name,
                string.Join(", ", Elements.Select(element => string.Format("Functions.Abs(value.{0})", element))));
            Dedent();
            WriteLine("}");
            WriteLine("/// <summary>");
            WriteLine("/// Returns a matrix that contains the lowest value from each pair of elements.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"value1\">The first matrix.</param>");
            WriteLine("/// <param name=\"value2\">The second matrix.</param>");
            WriteLine("/// <returns>The lowest of each element in left and the matching element in right.</returns>");
            if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
            WriteLine("public static {0} Min({0} value1, {0} value2)", Name);
            WriteLine("{");
            Indent();
            WriteLine("return new {0}({1});", Name,
                string.Join(", ", Elements.Select(element => string.Format("Functions.Min(value1.{0}, value2.{0})", element))));
            Dedent();
            WriteLine("}");
            WriteLine("/// <summary>");
            WriteLine("/// Returns a matrix that contains the highest value from each pair of elements.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"value1\">The first matrix.</param>");
            WriteLine("/// <param name=\"value2\">The second matrix.</param>");
            WriteLine("/// <returns>The highest of each element in left and the matching element in right.</returns>");
            if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
            WriteLine("public static {0} Max({0} value1, {0} value2)", Name);
            WriteLine("{");
            Indent();
            WriteLine("return new {0}({1});", Name,
                string.Join(", ", Elements.Select(element => string.Format("Functions.Max(value1.{0}, value2.{0})", element))));
            Dedent();
            WriteLine("}");
            WriteLine("/// <summary>");
            WriteLine("/// Constrains each element to a given range.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"value\">A matrix to constrain.</param>");
            WriteLine("/// <param name=\"min\">The minimum values for each element.</param>");
            WriteLine("/// <param name=\"max\">The maximum values for each element.</param>");
            WriteLine("/// <returns>A matrix with each element constrained to the given range.</returns>");
            if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
            WriteLine("public static {0} Clamp({0} value, {0} min, {0} max)", Name);
            WriteLine("{");
            Indent();
            WriteLine("return new {0}({1});", Name,
                string.Join(", ", Elements.Select(element => string.Format("Functions.Clamp(value.{0}, min.{0}, max.{0})", element))));
            Dedent();
            WriteLine("}");
            if (Type.IsReal)
            {
                WriteLine("/// <summary>");
                WriteLine("/// Constrains each element to the range 0 to 1.");
                WriteLine("/// </summary>");
                WriteLine("/// <param name=\"value\">A matrix to saturate.</param>");
                WriteLine("/// <returns>A matrix with each element constrained to the range 0 to 1.</returns>");
                if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
                WriteLine("public static {0} Saturate({0} value)", Name);
                WriteLine("{");
                Indent();
                WriteLine("return new {0}({1});", Name,
                    string.Join(", ", Elements.Select(element => string.Format("Functions.Saturate(value.{0})", element))));
                Dedent();
                WriteLine("}");
                WriteLine("/// <summary>");
                WriteLine("/// Returns a matrix where each element is the smallest integral value that");
                WriteLine("/// is greater than or equal to the specified element.");
                WriteLine("/// </summary>");
                WriteLine("/// <param name=\"value\">A matrix.</param>");
                WriteLine("/// <returns>The ceiling of value.</returns>");
                if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
                WriteLine("public static {0} Ceiling({0} value)", Name);
                WriteLine("{");
                Indent();
                WriteLine("return new {0}({1});", Name,
                    string.Join(", ", Elements.Select(element => string.Format("Functions.Ceiling(value.{0})", element))));
                Dedent();
                WriteLine("}");
                WriteLine("/// <summary>");
                WriteLine("/// Returns a matrix where each element is the largest integral value that");
                WriteLine("/// is less than or equal to the specified element.");
                WriteLine("/// </summary>");
                WriteLine("/// <param name=\"value\">A matrix.</param>");
                WriteLine("/// <returns>The floor of value.</returns>");
                if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
                WriteLine("public static {0} Floor({0} value)", Name);
                WriteLine("{");
                Indent();
                WriteLine("return new {0}({1});", Name,
                    string.Join(", ", Elements.Select(element => string.Format("Functions.Floor(value.{0})", element))));
                Dedent();
                WriteLine("}");
                WriteLine("/// <summary>");
                WriteLine("/// Returns a matrix where each element is the integral part of the specified element.");
                WriteLine("/// </summary>");
                WriteLine("/// <param name=\"value\">A matrix.</param>");
                WriteLine("/// <returns>The integral of value.</returns>");
                if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
                WriteLine("public static {0} Truncate({0} value)", Name);
                WriteLine("{");
                Indent();
                WriteLine("return new {0}({1});", Name,
                    string.Join(", ", Elements.Select(element => string.Format("Functions.Truncate(value.{0})", element))));
                Dedent();
                WriteLine("}");
                WriteLine("/// <summary>");
                WriteLine("/// Returns a matrix where each element is the fractional part of the specified element.");
                WriteLine("/// </summary>");
                WriteLine("/// <param name=\"value\">A matrix.</param>");
                WriteLine("/// <returns>The fractional of value.</returns>");
                if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
                WriteLine("public static {0} Fractional({0} value)", Name);
                WriteLine("{");
                Indent();
                WriteLine("return new {0}({1});", Name,
                    string.Join(", ", Elements.Select(element => string.Format("Functions.Fractional(value.{0})", element))));
                Dedent();
                WriteLine("}");
                WriteLine("/// <summary>");
                WriteLine("/// Returns a matrix where each element is rounded to the nearest integral value.");
                WriteLine("/// </summary>");
                WriteLine("/// <param name=\"value\">A matrix.</param>");
                WriteLine("/// <returns>The result of rounding value.</returns>");
                if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
                WriteLine("public static {0} Round({0} value)", Name);
                WriteLine("{");
                Indent();
                WriteLine("return new {0}({1});", Name,
                    string.Join(", ", Elements.Select(element => string.Format("Functions.Round(value.{0})", element))));
                Dedent();
                WriteLine("}");
                WriteLine("/// <summary>");
                WriteLine("/// Returns a matrix where each element is rounded to the nearest integral value.");
                WriteLine("/// </summary>");
                WriteLine("/// <param name=\"value\">A matrix.</param>");
                WriteLine("/// <param name=\"digits\">The number of fractional digits in the return value.</param>");
                WriteLine("/// <returns>The result of rounding value.</returns>");
                if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
                WriteLine("public static {0} Round({0} value, int digits)", Name);
                WriteLine("{");
                Indent();
                WriteLine("return new {0}({1});", Name,
                    string.Join(", ", Elements.Select(element => string.Format("Functions.Round(value.{0}, digits)", element))));
                Dedent();
                WriteLine("}");
                WriteLine("/// <summary>");
                WriteLine("/// Returns a matrix where each element is rounded to the nearest integral value.");
                WriteLine("/// </summary>");
                WriteLine("/// <param name=\"value\">A matrix.</param>");
                WriteLine("/// <param name=\"mode\">Specification for how to round value if it is midway between two other numbers.</param>");
                WriteLine("/// <returns>The result of rounding value.</returns>");
                if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
                WriteLine("public static {0} Round({0} value, MidpointRounding mode)", Name);
                WriteLine("{");
                Indent();
                WriteLine("return new {0}({1});", Name,
                    string.Join(", ", Elements.Select(element => string.Format("Functions.Round(value.{0}, mode)", element))));
                Dedent();
                WriteLine("}");
                WriteLine("/// <summary>");
                WriteLine("/// Returns a matrix where each element is rounded to the nearest integral value.");
                WriteLine("/// </summary>");
                WriteLine("/// <param name=\"value\">A matrix.</param>");
                WriteLine("/// <param name=\"digits\">The number of fractional digits in the return value.</param>");
                WriteLine("/// <param name=\"mode\">Specification for how to round value if it is midway between two other numbers.</param>");
                WriteLine("/// <returns>The result of rounding value.</returns>");
                if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
                WriteLine("public static {0} Round({0} value, int digits, MidpointRounding mode)", Name);
                WriteLine("{");
                Indent();
                WriteLine("return new {0}({1});", Name,
                    string.Join(", ", Elements.Select(element => string.Format("Functions.Round(value.{0}, digits, mode)", element))));
                Dedent();
                WriteLine("}");
                WriteLine("/// <summary>");
                WriteLine("/// Calculates the reciprocal of each element in the matrix.");
                WriteLine("/// </summary>");
                WriteLine("/// <param name=\"value\">A matrix.</param>");
                WriteLine("/// <returns>A matrix with the reciprocal of each of values elements.</returns>");
                if (!Type.IsCLSCompliant) { WriteLine("[CLSCompliant(false)]"); }
                WriteLine("public static {0} Reciprocal({0} value)", Name);
                WriteLine("{");
                Indent();
                WriteLine("return new {0}({1});", Name,
                    string.Join(", ", Elements.Select(element => string.Format("1 / value.{0}", element))));
                Dedent();
                WriteLine("}");
            }
            WriteLine("#endregion");
            #endregion 
            
            #region Submatrix
            WriteLine("#region Submatrix");
            if (Rows == 2 && Columns == 2)
            {
                WriteLine("/// <summary>");
                WriteLine("/// Returns the specified submatrix of the given matrix.");
                WriteLine("/// </summary>");
                WriteLine("/// <param name=\"matrix\">The matrix whose submatrix is to returned.</param>");
                WriteLine("/// <param name=\"row\">The row to be removed.</param>");
                WriteLine("/// <param name=\"column\">The column to be removed.</param>");
                WriteLine("public static {0} Submatrix({1} matrix, int row, int column)", Type, Name);
                WriteLine("{");
                Indent();
                RowBounds();
                ColumnBounds();
                Write("if(row == 0 && column == 0) { return "); Submatrix("matrix", 0, 0); WriteLine("; }");
                Write("else if(row == 0 && column == 1) { return "); Submatrix("matrix", 0, 1); WriteLine("; }");
                Write("else if(row == 1 && column == 0) { return "); Submatrix("matrix", 1, 0); WriteLine("; }");
                Write("else { return "); Submatrix("matrix", 1, 1); WriteLine("; }");
                Dedent();
                WriteLine("}");
            }
            else if (Rows == 2 || Columns == 2)
            {
                var minor = new Vector(Type, (Rows == 2 ? Columns : Rows) - 1);

                WriteLine("/// <summary>");
                WriteLine("/// Returns the specified submatrix of the given matrix.");
                WriteLine("/// </summary>");
                WriteLine("/// <param name=\"matrix\">The matrix whose submatrix is to returned.</param>");
                WriteLine("/// <param name=\"row\">The row to be removed.</param>");
                WriteLine("/// <param name=\"column\">The column to be removed.</param>");
                WriteLine("public static {0} Submatrix({1} matrix, int row, int column)", minor, Name);
                WriteLine("{");
                Indent();
                RowBounds();
                ColumnBounds();
                for (int i = 0; i < Rows; ++i)
                {
                    for (int j = 0; j < Columns; ++j)
                    {
                        if (i == 0 && j == 0)
                        {
                            WriteLine("if (row == {0} && column == {1})", i, j);
                        }
                        else if (i == Rows - 1 && j == Columns - 1)
                        {
                            WriteLine("else");
                        }
                        else
                        {
                            WriteLine("else if (row == {0} && column == {1})", i, j);
                        }
                        WriteLine("{");
                        Indent();
                        Write("return "); Submatrix("matrix", i, j); WriteLine(";");
                        Dedent();
                        WriteLine("}");
                    }
                }
                Dedent();
                WriteLine("}");
            }
            else
            {
                var minor = new Matrix(Type, Rows - 1, Columns - 1);

                WriteLine("/// <summary>");
                WriteLine("/// Returns the specified submatrix of the given matrix.");
                WriteLine("/// </summary>");
                WriteLine("/// <param name=\"matrix\">The matrix whose submatrix is to returned.</param>");
                WriteLine("/// <param name=\"row\">The row to be removed.</param>");
                WriteLine("/// <param name=\"column\">The column to be removed.</param>");
                WriteLine("public static {0} Submatrix({1} matrix, int row, int column)", minor, Name);
                WriteLine("{");
                Indent();
                RowBounds();
                ColumnBounds();
                for (int i = 0; i < Rows; ++i)
                {
                    for (int j = 0; j < Columns; ++j)
                    {
                        if (i == 0 && j == 0)
                        {
                            WriteLine("if (row == {0} && column == {1})", i, j);
                        }
                        else if (i == Rows - 1 && j == Columns - 1)
                        {
                            WriteLine("else");
                        }
                        else 
                        {
                            WriteLine("else if (row == {0} && column == {1})", i, j);
                        }
                        WriteLine("{");
                        Indent();
                        WriteLine("return new {0}({1});", minor,
                            string.Join(", ", Elements.Where(element => element.Row != i && element.Column != j).Select(
                                e => string.Format("matrix.{0}", e))));
                        Dedent();
                        WriteLine("}");
                    }
                }
                Dedent();
                WriteLine("}");
            }
            WriteLine("#endregion");
            #endregion

            #region Invert, Determinant
            if (Rows == Columns)
            {
                WriteLine("#region Invert, Determinant");

                WriteLine("/// <summary>");
                WriteLine("/// Calculates the inverse of the specified matrix.");
                WriteLine("/// </summary>");
                WriteLine("/// <param name=\"matrix\">The matrix whose inverse is to be calculated.</param>");
                WriteLine("/// <param name=\"determinant\">When the method completes, contains the determinant of the matrix.</param>");
                WriteLine("public static {0} Invert({0} matrix, out {1} determinant)", Name, Type);
                WriteLine("{");
                Indent();
                if (Rows == 2)
                {
                    WriteLine("determinant = matrix.M11 * matrix.M22 - matrix.M12 * matrix.M21;");
                    WriteLine("return new {0}(determinant * matrix.M22, determinant * -matrix.M12, determinant * -matrix.M21, determinant * matrix.M11);", Name);                    
                }
                else
                {
                    for (int row = 0; row < Rows; ++row)
                    {
                        for (int column = 0; column < Columns; ++column)
                        {
                            Write("var cofactor{1}{0} = {2}", row, column, Math.Pow(-1, column + row) == -1 ? "-" : "");
                            Write("Determinant(", row, column); Submatrix("matrix", row, column); WriteLine(");");
                        }
                    }

                    WriteLine("determinant = {0};", string.Join(" + ",
                        Enumerable.Range(0, Rows).Select(row => string.Format("matrix.M{0}1 * cofactor{1}0", row + 1, row))));

                    WriteLine("return new {0}({1}) / determinant;", Name,
                        string.Join(", ", Elements.Select(element => string.Format("cofactor{0}{1}", element.Column, element.Row))));
                }
                Dedent();
                WriteLine("}");

                WriteLine("/// <summary>");
                WriteLine("/// Calculates the inverse of the specified matrix.");
                WriteLine("/// </summary>");
                WriteLine("/// <param name=\"matrix\">The matrix whose inverse is to be calculated.</param>");
                WriteLine("/// <param name=\"determinant\">When the method completes, contains the determinant of the matrix.</param>");
                WriteLine("public static {0} Invert({0} matrix)", Name);
                WriteLine("{");
                Indent();
                WriteLine("{0} determinant;", Type);
                WriteLine("return Invert(matrix, out determinant);");
                Dedent();
                WriteLine("}");

                WriteLine("/// <summary>");
                WriteLine("/// Calculates the determinant of the matrix.");
                WriteLine("/// </summary>");
                WriteLine("/// <returns>The determinant of the matrix.</returns>");
                WriteLine("public static {0} Determinant({1} matrix)", Type, Name);
                WriteLine("{");
                Indent();
                if (Rows == 2)
                {
                    WriteLine("return matrix.M11 * matrix.M22 - matrix.M12 * matrix.M21;");
                }
                else
                {
                    for (int row = 0; row < Rows; ++row)
                    {
                        Write("var minor{0} = Determinant(", row); Submatrix("matrix", row, 0); WriteLine(");");
                    }
                    for (int row = 0; row < Rows; ++row)
                    {
                        WriteLine("var cofactor{0} = {1}minor{0};", row, Math.Pow(-1, 2+row) == -1 ? "-" : "");
                    }
                    
                    WriteLine("return {0};", string.Join(" + ", 
                        Enumerable.Range(0, Rows).Select(row => string.Format("matrix.M{0}1 * cofactor{1}", row + 1, row))));
                }
                Dedent();
                WriteLine("}");

                WriteLine("#endregion");
            }
            #endregion

            #region Transpose
            Matrix transpose = new Matrix(Type, Columns, Rows);
            WriteLine("#region Transpose");
            WriteLine("/// <summary>");
            WriteLine("/// Calculates the transpose of the specified matrix.");
            WriteLine("/// </summary>");
            WriteLine("/// <param name=\"matrix\">The matrix whose transpose is to be calculated.</param>");
            WriteLine("/// <returns>The transpose of the specified matrix.</returns>");
            WriteLine("public static {0} Transpose({1} matrix)", transpose, Name);
            WriteLine("{");
            Indent();
            WriteLine("return new {0}({1});", transpose, string.Join(", ",
                transpose.Elements.Select(element => string.Format("matrix.M{0}{1}", element.Column + 1, element.Row + 1))));
            Dedent();
            WriteLine("}");
            WriteLine("#endregion");
            #endregion

            Dedent();
            WriteLine("}");
        }
예제 #12
0
파일: Matrix.cs 프로젝트: Frassle/Ibasa
 private void Submatrix(string matrix, int row, int column)
 {
     if (Rows == 2 && Columns == 2)
     {
         if (row == 0 && column == 0) { Write(matrix + ".M22"); }
         if (row == 0 && column == 1) { Write(matrix + ".M21"); }
         if (row == 1 && column == 0) { Write(matrix + ".M12"); }
         if (row == 1 && column == 1) { Write(matrix + ".M11"); }
     }
     else if (Rows == 2 || Columns == 2)
     {
         var minor = new Vector(Type, (Rows == 2 ? Columns : Rows) - 1);
         
         Write("new {0}({1})", minor,
                     string.Join(", ", Elements.Where(element => element.Row != row && element.Column != column).Select(
                         e => string.Format("{0}.{1}", matrix, e))));
     }
     else
     {
         var minor = new Matrix(Type, Rows - 1, Columns - 1);
         
         Write("new {0}({1})", minor,
             string.Join(", ", Elements.Where(element => element.Row != row && element.Column != column).Select(
                 e => string.Format("{0}.{1}", matrix, e))));
     }
 }
예제 #13
0
파일: Matrix.cs 프로젝트: Frassle/Ibasa
        private void Properties()
        {
            WriteLine("#region Properties");

            WriteLine("public {0} this[int row, int column]", Type);
            WriteLine("{");
            Indent();
            WriteLine("get");
            WriteLine("{");
            Indent();
            RowBounds();
            ColumnBounds();
            WriteLine("int index = row + column * {0};", Rows);
            WriteLine("return this[index];");
            Dedent();
            WriteLine("}");
            Dedent();
            WriteLine("}");

            WriteLine("public {0} this[int index]", Type);
            WriteLine("{");
            Indent();
            WriteLine("get");
            WriteLine("{");
            Indent();
            WriteLine("if (index < 0 || index > {0})", (Rows * Columns) - 1);
            Indent();
            WriteLine("throw new ArgumentOutOfRangeException(\"index\", \"Indices for {0} run from 0 to {1}, inclusive.\");", Name, (Rows * Columns) - 1);
            Dedent();
            WriteLine("switch (index)");
            WriteLine("{");
            Indent();
            foreach(var element in Elements)
            {
                WriteLine("case {0}: return {1};", element.Index, element);
            }
            Dedent();
            WriteLine("}");
            WriteLine("return 0;");
            Dedent();
            WriteLine("}");
            Dedent();
            WriteLine("}");

            var rowVector = new Vector(Type, Columns);

            WriteLine("public {0} GetRow(int row)", rowVector);
            WriteLine("{");
            Indent();
            RowBounds();
            WriteLine("switch (row)");
            WriteLine("{");
            Indent();
            for(int row = 0; row < Rows; ++row)
            {
                WriteLine("case {0}:", row);
                Indent();
                WriteLine("return new {0}({1});", rowVector,
                    string.Join(", ", Enumerable.Range(0, Columns).Select(column => string.Format("M{0}{1}", row + 1, column + 1))));
                Dedent();
            }
            Dedent();
            WriteLine("}");
            WriteLine("return {0}.Zero;", rowVector);
            Dedent();
            WriteLine("}");

            var columnVector = new Vector(Type, Rows);

            WriteLine("public {0} GetColumn(int column)", columnVector);
            WriteLine("{");
            Indent();
            ColumnBounds();
            WriteLine("switch (column)");
            WriteLine("{");
            Indent();
            for (int column = 0; column < Columns; ++column)
            {
                WriteLine("case {0}:", column);
                Indent();
                WriteLine("return new {0}({1});", columnVector,
                    string.Join(", ", Enumerable.Range(0, Rows).Select(row => string.Format("M{0}{1}", row + 1, column + 1))));
                Dedent();
            }
            Dedent();
            WriteLine("}");
            WriteLine("return {0}.Zero;", columnVector);
            Dedent();
            WriteLine("}");

            WriteLine("public {0}[] ToArray()", Type);
            WriteLine("{");
            Indent();
            WriteLine("return new {0}[]", Type);
            WriteLine("{");
            Indent();
            WriteLine(string.Join(", ", Elements.Select(element => string.Format("M{0}{1}", element.Row + 1, element.Column + 1))));
            Dedent();
            WriteLine("};");
            Dedent();
            WriteLine("}");

            WriteLine("#endregion");
        }
예제 #14
0
파일: Color.cs 프로젝트: Frassle/Ibasa
        void Conversions()
        {
            WriteLine("#region Conversions");

            foreach (var type in Color.Types.Where(t => t != Type))
            {
                string imex = type.IsImplicitlyConvertibleTo(Type) ? "implicit" : "explicit";

                Color other = new Color(type);

                var casts = string.Join(", ",
                    Components.Select(component => string.Format("({0})value.{1}", Type, component)));

                WriteLine("/// <summary>");
                WriteLine("/// Defines an {0} conversion of a {1} value to a {2}.", imex, other, Name);
                WriteLine("/// </summary>");
                WriteLine("/// <param name=\"value\">The value to convert to a {0}.</param>", Name);
                WriteLine("/// <returns>A {0} that has all components equal to value.</returns>", Name);
                if (Type.IsCLSCompliant && !type.IsCLSCompliant)
                {
                    WriteLine("[CLSCompliant(false)]");
                }
                WriteLine("public static {0} operator {1}({2} value)", imex, Name, other);
                WriteLine("{");
                Indent();
                WriteLine("return new {0}({1});", Name, casts);
                Dedent();
                WriteLine("}");
            }

            foreach (var type in Vector.Types)
            {
                string to_vector_imex = Type.IsImplicitlyConvertibleTo(type) ? "implicit" : "explicit";
                string to_color_imex = type.IsImplicitlyConvertibleTo(Type) ? "implicit" : "explicit";

                Vector vector = new Vector(type, 4);

                var to_vector = string.Join(", ",
                    this.Components.Select(component => string.Format("({0})value.{1}", type, component)));

                var to_color = string.Join(", ",
                    vector.Components.Select(component => string.Format("({0})value.{1}", Type, component)));

                WriteLine("/// <summary>");
                WriteLine("/// Defines an {0} conversion of a {1} value to a {2}.", to_vector_imex, Name, vector);
                WriteLine("/// </summary>");
                WriteLine("/// <param name=\"value\">The value to convert to a {0}.</param>", vector);
                WriteLine("/// <returns>A {0} that has all components equal to value.</returns>", vector);
                if (Type.IsCLSCompliant && !type.IsCLSCompliant)
                {
                    WriteLine("[CLSCompliant(false)]");
                }
                WriteLine("public static {0} operator {1}({2} value)", to_vector_imex, vector, Name);
                WriteLine("{");
                Indent();
                WriteLine("return new {0}({1});", vector, to_vector);
                Dedent();
                WriteLine("}");

                WriteLine("/// <summary>");
                WriteLine("/// Defines an {0} conversion of a {1} value to a {2}.", to_color_imex, vector, Name);
                WriteLine("/// </summary>");
                WriteLine("/// <param name=\"value\">The value to convert to a {0}.</param>", Name);
                WriteLine("/// <returns>A {0} that has all components equal to value.</returns>", Name);
                if (Type.IsCLSCompliant && !type.IsCLSCompliant)
                {
                    WriteLine("[CLSCompliant(false)]");
                }
                WriteLine("public static {0} operator {1}({2} value)", to_color_imex, Name, vector);
                WriteLine("{");
                Indent();
                WriteLine("return new {0}({1});", Name, to_color);
                Dedent();
                WriteLine("}");
            }

            foreach (var type in Vector.Types)
            {
                Vector vector = new Vector(type, 3);

                var to_vector = string.Join(", ",
                    string.Format("({0})value.R", type),
                    string.Format("({0})value.G", type),
                    string.Format("({0})value.B", type));

                var to_color = string.Join(", ",
                    string.Format("({0})value.X", Type),
                    string.Format("({0})value.Y", Type),
                    string.Format("({0})value.Z", Type), "1");

                WriteLine("/// <summary>");
                WriteLine("/// Defines an explicit conversion of a {0} value to a {1}.", Name, vector);
                WriteLine("/// </summary>");
                WriteLine("/// <param name=\"value\">The value to convert to a {0}.</param>", vector);
                WriteLine("/// <returns>A {0} that has all components equal to value.</returns>", vector);
                if (Type.IsCLSCompliant && !type.IsCLSCompliant)
                {
                    WriteLine("[CLSCompliant(false)]");
                }
                WriteLine("public static explicit operator {0}({1} value)", vector, Name);
                WriteLine("{");
                Indent();
                WriteLine("return new {0}({1});", vector, to_vector);
                Dedent();
                WriteLine("}");

                WriteLine("/// <summary>");
                WriteLine("/// Defines an explicit conversion of a {0} value to a {1}.", vector, Name);
                WriteLine("/// </summary>");
                WriteLine("/// <param name=\"value\">The value to convert to a {0}.</param>", Name);
                WriteLine("/// <returns>A explicit that has all components equal to value.</returns>", Name);
                if (Type.IsCLSCompliant && !type.IsCLSCompliant)
                {
                    WriteLine("[CLSCompliant(false)]");
                }
                WriteLine("public static explicit operator {0}({1} value)", Name, vector);
                WriteLine("{");
                Indent();
                WriteLine("return new {0}({1});", Name, to_color);
                Dedent();
                WriteLine("}");
            }

            WriteLine("#endregion");
        }