/// <summary>
        /// Reads a matrix file generated by Spice 3f5.
        /// </summary>
        /// <param name="matFilename">The matrix filename.</param>
        /// <param name="vecFilename">The vector filename.</param>
        /// <returns></returns>
        protected Solver <double> ReadSpice3f5File(string matFilename, string vecFilename)
        {
            var solver = new RealSolver();

            // Read the spice file
            string line;

            using (var reader = new StreamReader(matFilename))
            {
                // The file is organized using (row) (column) (value) (imag value)
                while (!reader.EndOfStream && (line = reader.ReadLine()) != null)
                {
                    if (line == "first")
                    {
                        continue;
                    }
                    var match = Regex.Match(line, @"^(?<size>\d+)\s+(complex|real)$");

                    // Try to read an element
                    match = Regex.Match(line, @"^(?<row>\d+)\s+(?<col>\d+)\s+(?<value>[^\s]+)(\s+[^\s]+)?$");
                    if (match.Success)
                    {
                        int row   = int.Parse(match.Groups["row"].Value);
                        int col   = int.Parse(match.Groups["col"].Value);
                        var value = double.Parse(match.Groups["value"].Value, CultureInfo.InvariantCulture);
                        solver.GetMatrixElement(row, col).Value = value;
                    }
                }
            }

            // Read the vector file
            using (var reader = new StreamReader(vecFilename))
            {
                var index = 1;
                while (!reader.EndOfStream && (line = reader.ReadLine()) != null)
                {
                    var value = double.Parse(line, CultureInfo.InvariantCulture);
                    solver.GetRhsElement(index).Value = value;
                    index++;
                }
            }

            return(solver);
        }
        public void When_QuickDiagonalPivoting_Expect_NoException()
        {
            // Build the solver with only the quick diagonal pivoting
            var solver   = new RealSolver();
            var strategy = (Markowitz <double>)solver.Strategy;

            strategy.Strategies.Clear();
            strategy.Strategies.Add(new MarkowitzQuickDiagonal <double>());

            // Build the matrix that should be solvable using only the singleton pivoting strategy
            double[][] matrix =
            {
                new[] {    1, 0.5,     0,   0 },
                new[] { -0.5,   5,     4,   0 },
                new[] {    0,   3,     2, 0.1 },
                new[] {    0,   0, -0.01,   3 }
            };
            double[] rhs = { 0, 0, 0, 0 };
            for (var r = 0; r < matrix.Length; r++)
            {
                for (var c = 0; c < matrix[r].Length; c++)
                {
                    if (!matrix[r][c].Equals(0.0))
                    {
                        solver.GetMatrixElement(r + 1, c + 1).Value = matrix[r][c];
                    }
                }
                if (!rhs[r].Equals(0.0))
                {
                    solver.GetRhsElement(r + 1).Value = rhs[r];
                }
            }

            // This should run without throwing an exception
            solver.OrderAndFactor();
        }