public override void AddVectorToScaledVector(Complex32[] y, Complex32 alpha, Complex32[] x, Complex32[] result)
        {
            if (y == null)
            {
                throw new ArgumentNullException("y");
            }

            if (x == null)
            {
                throw new ArgumentNullException("x");
            }

            if (y.Length != x.Length)
            {
                throw new ArgumentException(Resources.ArgumentVectorsSameLength);
            }

            if (!ReferenceEquals(y, result))
            {
                Array.Copy(y, 0, result, 0, y.Length);
            }

            if (alpha == Complex32.Zero)
            {
                return;
            }

            SafeNativeMethods.c_axpy(y.Length, alpha, x, result);
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="DenseVector"/> class with a given size
 /// and each element set to the given value;
 /// </summary>
 /// <param name="size">
 /// the size of the vector.
 /// </param>
 /// <param name="value">
 /// the value to set each element to.
 /// </param>
 /// <exception cref="ArgumentException">
 /// If <paramref name="size"/> is less than one.
 /// </exception>
 public DenseVector(int size, Complex32 value) : this(size)
 {
     for (var index = 0; index < Data.Length; index++)
     {
         Data[index] = value;
     }
 }
Beispiel #3
0
        /// <summary>
        /// Initializes a new instance of the <see cref="DenseQR"/> class. This object will compute the
        /// QR factorization when the constructor is called and cache it's factorization.
        /// </summary>
        /// <param name="matrix">The matrix to factor.</param>
        /// <param name="method">The QR factorization method to use.</param>
        /// <exception cref="ArgumentNullException">If <paramref name="matrix"/> is <c>null</c>.</exception>
        /// <exception cref="ArgumentException">If <paramref name="matrix"/> row count is less then column count</exception>
        public static DenseQR Create(DenseMatrix matrix, QRMethod method = QRMethod.Full)
        {
            if (matrix.RowCount < matrix.ColumnCount)
            {
                throw Matrix.DimensionsDontMatch<ArgumentException>(matrix);
            }

            var tau = new Complex32[Math.Min(matrix.RowCount, matrix.ColumnCount)];
            Matrix<Complex32> q;
            Matrix<Complex32> r;

            if (method == QRMethod.Full)
            {
                r = matrix.Clone();
                q = new DenseMatrix(matrix.RowCount);
                Control.LinearAlgebraProvider.QRFactor(((DenseMatrix) r).Values, matrix.RowCount, matrix.ColumnCount, ((DenseMatrix) q).Values, tau);
            }
            else
            {
                q = matrix.Clone();
                r = new DenseMatrix(matrix.ColumnCount);
                Control.LinearAlgebraProvider.ThinQRFactor(((DenseMatrix) q).Values, matrix.RowCount, matrix.ColumnCount, ((DenseMatrix) r).Values, tau);
            }

            return new DenseQR(q, r, method, tau);
        }
        public override double MatrixNorm(Norm norm, int rows, int columns, Complex32[] matrix)
        {
            if (matrix == null)
            {
                throw new ArgumentNullException("matrix");
            }

            if (rows <= 0)
            {
                throw new ArgumentException(Resources.ArgumentMustBePositive, "rows");
            }

            if (columns <= 0)
            {
                throw new ArgumentException(Resources.ArgumentMustBePositive, "columns");
            }

            if (matrix.Length < rows * columns)
            {
                throw new ArgumentException(string.Format(Resources.ArrayTooSmall, rows * columns), "matrix");
            }

            var work = new float[rows];
            return SafeNativeMethods.c_matrix_norm((byte)norm, rows, columns, matrix, work);
        }
        /// <summary>
        /// Does a point wise add of two arrays <c>z = x + y</c>. This can be used
        /// to add vectors or matrices.
        /// </summary>
        /// <param name="x">The array x.</param>
        /// <param name="y">The array y.</param>
        /// <param name="result">The result of the addition.</param>
        /// <remarks>There is no equivalent BLAS routine, but many libraries
        /// provide optimized (parallel and/or vectorized) versions of this
        /// routine.</remarks>
        public virtual void AddArrays(Complex32[] x, Complex32[] y, Complex32[] result)
        {
            if (y == null)
            {
                throw new ArgumentNullException("y");
            }

            if (x == null)
            {
                throw new ArgumentNullException("x");
            }

            if (result == null)
            {
                throw new ArgumentNullException("result");
            }

            if (y.Length != x.Length || y.Length != result.Length)
            {
                throw new ArgumentException(Resources.ArgumentVectorsSameLength);
            }

            CommonParallel.For(0, y.Length, 4096, (a, b) =>
            {
                for (int i = a; i < b; i++)
                {
                    result[i] = x[i] + y[i];
                }
            });
        }
        /// <summary>
        /// Adds a scaled vector to another: <c>result = y + alpha*x</c>.
        /// </summary>
        /// <param name="y">The vector to update.</param>
        /// <param name="alpha">The value to scale <paramref name="x"/> by.</param>
        /// <param name="x">The vector to add to <paramref name="y"/>.</param>
        /// <param name="result">The result of the addition.</param>
        /// <remarks>This is similar to the AXPY BLAS routine.</remarks>
        public virtual void AddVectorToScaledVector(Complex32[] y, Complex32 alpha, Complex32[] x, Complex32[] result)
        {
            if (y == null)
            {
                throw new ArgumentNullException("y");
            }

            if (x == null)
            {
                throw new ArgumentNullException("x");
            }

            if (y.Length != x.Length)
            {
                throw new ArgumentException(Resources.ArgumentVectorsSameLength);
            }

            if (alpha.IsZero())
            {
                CommonParallel.For(0, y.Length, index => result[index] = y[index]);
            }
            else if (alpha.IsOne())
            {
                CommonParallel.For(0, y.Length, index => result[index] = y[index] + x[index]);
            }
            else
            {
                CommonParallel.For(0, y.Length, index => result[index] = y[index] + (alpha * x[index]));
            }
        }
        /// <summary>
        /// Does a point wise add of two arrays <c>z = x + y</c>. This can be used 
        /// to add vectors or matrices.
        /// </summary>
        /// <param name="x">The array x.</param>
        /// <param name="y">The array y.</param>
        /// <param name="result">The result of the addition.</param>
        /// <remarks>There is no equivalent BLAS routine, but many libraries
        /// provide optimized (parallel and/or vectorized) versions of this
        /// routine.</remarks>
        public virtual void AddArrays(Complex32[] x, Complex32[] y, Complex32[] result)
        {
            if (y == null)
            {
                throw new ArgumentNullException("y");
            }

            if (x == null)
            {
                throw new ArgumentNullException("x");
            }

            if (result == null)
            {
                throw new ArgumentNullException("result");
            }

            if (y.Length != x.Length || y.Length != result.Length)
            {
                throw new ArgumentException(Resources.ArgumentVectorsSameLength);
            }

            if (Control.ParallelizeOperation(x.Length))
            {
                CommonParallel.For(0, y.Length, index => { result[index] = x[index] + y[index]; });
            }
            else
            {
                for (var index = 0; index < x.Length; index++)
                {
                    result[index] = x[index] + y[index];
                }
            }
        }
        public virtual Complex32 TheveninVoltage(Node referenceNode, Complex32 ?W = null)
        {
            Complex32 v = 0;
            Dipole compo1 = null;
            Node node1 = null;
            foreach (var item in Components)
            {
                if (item.Nodes[0] == referenceNode || item.Nodes[1] == referenceNode)
                {
                    compo1 = item;
                    break;
                }
            }
            node1 = referenceNode;
            do
            {
                if (compo1 is Branch)
                    v += ((Branch)compo1).TheveninVoltage(node1, W);                    
                else
                    v += compo1.voltage(node1, W);
                node1 = compo1.OtherNode(node1);
                compo1 = node1.OtherComponent(compo1);
            } while (InternalNodes.Contains(node1));

            return v;
        }
Beispiel #9
0
        /// <summary>
        /// Initializes a new instance of the <see cref="UserQR"/> class. This object will compute the
        /// QR factorization when the constructor is called and cache it's factorization.
        /// </summary>
        /// <param name="matrix">The matrix to factor.</param>
        /// <param name="method">The QR factorization method to use.</param>
        /// <exception cref="ArgumentNullException">If <paramref name="matrix"/> is <c>null</c>.</exception>
        public static UserQR Create(Matrix<Complex32> matrix, QRMethod method = QRMethod.Full)
        {
            if (matrix.RowCount < matrix.ColumnCount)
            {
                throw Matrix.DimensionsDontMatch<ArgumentException>(matrix);
            }

            Matrix<Complex32> q;
            Matrix<Complex32> r;

            var minmn = Math.Min(matrix.RowCount, matrix.ColumnCount);
            var u = new Complex32[minmn][];

            if (method == QRMethod.Full)
            {
                r = matrix.Clone();
                q = Matrix<Complex32>.Build.SameAs(matrix, matrix.RowCount, matrix.RowCount);

                for (var i = 0; i < matrix.RowCount; i++)
                {
                    q.At(i, i, 1.0f);
                }

                for (var i = 0; i < minmn; i++)
                {
                    u[i] = GenerateColumn(r, i, i);
                    ComputeQR(u[i], r, i, matrix.RowCount, i + 1, matrix.ColumnCount, Control.MaxDegreeOfParallelism);
                }

                for (var i = minmn - 1; i >= 0; i--)
                {
                    ComputeQR(u[i], q, i, matrix.RowCount, i, matrix.RowCount, Control.MaxDegreeOfParallelism);
                }
            }
            else
            {
                q = matrix.Clone();

                for (var i = 0; i < minmn; i++)
                {
                    u[i] = GenerateColumn(q, i, i);
                    ComputeQR(u[i], q, i, matrix.RowCount, i + 1, matrix.ColumnCount, Control.MaxDegreeOfParallelism);
                }

                r = q.SubMatrix(0, matrix.ColumnCount, 0, matrix.ColumnCount);
                q.Clear();

                for (var i = 0; i < matrix.ColumnCount; i++)
                {
                    q.At(i, i, 1.0f);
                }

                for (var i = minmn - 1; i >= 0; i--)
                {
                    ComputeQR(u[i], q, i, matrix.RowCount, i, matrix.ColumnCount, Control.MaxDegreeOfParallelism);
                }
            }

            return new UserQR(q, r, method);
        }
Beispiel #10
0
        /// <summary>
        /// Initializes a new instance of the <see cref="DenseQR"/> class. This object will compute the
        /// QR factorization when the constructor is called and cache it's factorization.
        /// </summary>
        /// <param name="matrix">The matrix to factor.</param>
        /// <param name="method">The QR factorization method to use.</param>
        /// <exception cref="ArgumentNullException">If <paramref name="matrix"/> is <c>null</c>.</exception>
        /// <exception cref="ArgumentException">If <paramref name="matrix"/> row count is less then column count</exception>
        public DenseQR(DenseMatrix matrix, QRMethod method = QRMethod.Full)
        {
            if (matrix == null)
            {
                throw new ArgumentNullException("matrix");
            }

            if (matrix.RowCount < matrix.ColumnCount)
            {
                throw Matrix.DimensionsDontMatch<ArgumentException>(matrix);
            }

            Tau = new Complex32[Math.Min(matrix.RowCount, matrix.ColumnCount)];

            if (method == QRMethod.Full)
            {
                MatrixR = matrix.Clone();
                MatrixQ = new DenseMatrix(matrix.RowCount);
                Control.LinearAlgebraProvider.QRFactor(((DenseMatrix)MatrixR).Values, matrix.RowCount, matrix.ColumnCount,
                                                       ((DenseMatrix)MatrixQ).Values, Tau);
            }
            else
            {
                MatrixQ = matrix.Clone();
                MatrixR = new DenseMatrix(matrix.ColumnCount);
                Control.LinearAlgebraProvider.ThinQRFactor(((DenseMatrix)MatrixQ).Values, matrix.RowCount, matrix.ColumnCount,
                                                       ((DenseMatrix)MatrixR).Values, Tau);
            }
        }
Beispiel #11
0
        /// <summary>
        /// Initializes a new instance of the <see cref="UserQR"/> class. This object will compute the
        /// QR factorization when the constructor is called and cache it's factorization.
        /// </summary>
        /// <param name="matrix">The matrix to factor.</param>
        /// <exception cref="ArgumentNullException">If <paramref name="matrix"/> is <c>null</c>.</exception>
        public UserQR(Matrix<Complex32> matrix)
        {
            if (matrix == null)
            {
                throw new ArgumentNullException("matrix");
            }

            if (matrix.RowCount < matrix.ColumnCount)
            {
                throw new ArgumentException(Resources.ArgumentMatrixDimensions);
            }

            MatrixR = matrix.Clone();
            MatrixQ = matrix.CreateMatrix(matrix.RowCount, matrix.RowCount);

            for (var i = 0; i < matrix.RowCount; i++)
            {
                MatrixQ.At(i, i, 1.0f);
            }

            var minmn = Math.Min(matrix.RowCount, matrix.ColumnCount);
            var u = new Complex32[minmn][];
            for (var i = 0; i < minmn; i++)
            {
                u[i] = GenerateColumn(MatrixR, i, i);
                ComputeQR(u[i], MatrixR, i, matrix.RowCount, i + 1, matrix.ColumnCount, Control.NumberOfParallelWorkerThreads);
            }

            for (var i = minmn - 1; i >= 0; i--)
            {
                ComputeQR(u[i], MatrixQ, i, matrix.RowCount, i, matrix.RowCount, Control.NumberOfParallelWorkerThreads);
            }
        }
Beispiel #12
0
 /// <summary>
 /// Initializes a new instance of the <see cref="DenseMatrix"/> class. This matrix is square with a given size.
 /// </summary>
 /// <param name="order">the size of the square matrix.</param>
 /// <exception cref="ArgumentException">
 /// If <paramref name="order"/> is less than one.
 /// </exception>
 public DenseMatrix(int order)
     : base(order)
 {
     _rowCount = order;
     _columnCount = order;
     Data = new Complex32[order * order];
 }
Beispiel #13
0
 /// <summary>
 /// Initializes a new instance of the <see cref="DenseMatrix"/> class.
 /// </summary>
 /// <param name="rows">
 /// The number of rows.
 /// </param>
 /// <param name="columns">
 /// The number of columns.
 /// </param>
 public DenseMatrix(int rows, int columns)
     : base(rows, columns)
 {
     _rowCount = rows;
     _columnCount = columns;
     Data = new Complex32[rows * columns];
 }
        /// <summary>
        /// Returns the smallest absolute value from the unsorted data array.
        /// Returns NaN if data is empty or any entry is NaN.
        /// </summary>
        /// <param name="data">Sample array, no sorting is assumed.</param>
        public static Complex32 MinimumMagnitudePhase(Complex32[] data)
        {
            if (data.Length == 0)
            {
                return new Complex32(float.NaN, float.NaN);
            }

            float minMagnitude = float.PositiveInfinity;
            Complex32 min = new Complex32(float.PositiveInfinity, float.PositiveInfinity);
            for (int i = 0; i < data.Length; i++)
            {
                float magnitude = data[i].Magnitude;
                if (float.IsNaN(magnitude))
                {
                    return new Complex32(float.NaN, float.NaN);
                }
                if (magnitude < minMagnitude || magnitude == minMagnitude && data[i].Phase < min.Phase)
                {
                    minMagnitude = magnitude;
                    min = data[i];
                }
            }

            return min;
        }
 public override Complex32 Impedance(Complex32? W = null)
 {
     if (W == null || W.Value.IsZero())
         return Complex32.PositiveInfinity;
     // 1/jWC
     // 1/SC
     return (W.Value * new Complex32((float)Value,0)).Reciprocal();
 }
 public override Complex32 voltage(Node ReferenceNode, Complex32 ?W)
 {
     if (ReferenceNode == Nodes[0])
         return Voltage;
     if (ReferenceNode == Nodes[1])
         return -Voltage;
     return Complex32.NaN;
 }
 public override Complex32 Current(Node referenceNode, Complex32? W = null)
 {
     Complex32 i = Voltage / Impedance(W);
     if (referenceNode == Nodes[0])
         return i;
     else
         return -i;
 }
 public virtual Complex32 Current(Node referenceNode, Complex32? W = null)
 {
     //el signo contrario al pensado, entra por neagtivo y sale por positivo
     if (referenceNode == Nodes[0])
         return -current;
     else
         return current;
 }
 public override Complex32 Impedance(Complex32 ?W)
 {
     if (W == null)
         return Complex32.Zero;
     //jW*L
     //S*L
     Complex32 L = new Complex32((float) Value, 0);
     return W.Value * L;
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="DenseMatrix"/> class with all entries set to a particular value.
 /// </summary>
 /// <param name="rows">
 /// The number of rows.
 /// </param>
 /// <param name="columns">
 /// The number of columns.
 /// </param>
 /// <param name="value">The value which we assign to each element of the matrix.</param>
 public DenseMatrix(int rows, int columns, Complex32 value)
     : base(rows, columns)
 {
     Data = new Complex32[rows * columns];
     for (var i = 0; i < Data.Length; i++)
     {
         Data[i] = value;
     }
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="DiagonalMatrix"/> class with all entries set to a particular value.
 /// </summary>
 /// <param name="rows">
 /// The number of rows.
 /// </param>
 /// <param name="columns">
 /// The number of columns.
 /// </param>
 /// <param name="value">The value which we assign to each element of the matrix.</param>
 public DiagonalMatrix(int rows, int columns, Complex32 value)
     : base(rows, columns)
 {
     Data = new Complex32[Math.Min(rows, columns)];
     for (var i = 0; i < Data.Length; i++)
     {
         Data[i] = value;
     }
 }
 public void CanAddArrays()
 {
     var result = new Complex32[_y.Length];
     Control.LinearAlgebraProvider.AddArrays(_x, _y, result);
     for (var i = 0; i < result.Length; i++)
     {
         Assert.AreEqual(_x[i] + _y[i], result[i]);
     }
 }
        public void CanCreateSparseVectorFromArray()
        {
            var data = new Complex32[Data.Length];
            Array.Copy(Data, data, Data.Length);
            var vector = SparseVector.OfEnumerable(data);

            for (var i = 0; i < data.Length; i++)
            {
                Assert.AreEqual(data[i], vector[i]);
            }
        }
 public void CanFormatComplexToString(float real, float imag, string expected)
 {
     var numberFormat = NumberFormatInfo.CurrentInfo;
     var a = new Complex32(real, imag);
     Assert.AreEqual(
         String.Format(
             expected,
             numberFormat.NumberDecimalSeparator,
             numberFormat.NaNSymbol,
             numberFormat.PositiveInfinitySymbol),
         a.ToString());
 }
        public void CanWriteComplex32Matrices()
        {
            var mat1 = new LinearAlgebra.Complex32.DenseMatrix(5, 3);
            for (var i = 0; i < mat1.ColumnCount; i++)
            {
                mat1[i, i] = new Complex32(i + .1f, i + .1f);
            }

            var mat2 = new LinearAlgebra.Complex32.DenseMatrix(4, 5);
            for (var i = 0; i < mat2.RowCount; i++)
            {
                mat2[i, i] = new Complex32(i + .1f, i + .1f);
            }

            var mat3 = new LinearAlgebra.Complex32.SparseMatrix(5, 4);
            mat3[0, 0] = new Complex32(1.1f, 1.1f);
            mat3[0, 2] = new Complex32(2.2f, 2.2f);
            mat3[4, 3] = new Complex32(3.3f, 3.3f);

            var mat4 = new LinearAlgebra.Complex32.SparseMatrix(3, 5);
            mat4[0, 0] = new Complex32(1.1f, 1.1f);
            mat4[0, 2] = new Complex32(2.2f, 2.2f);
            mat4[2, 4] = new Complex32(3.3f, 3.3f);

            var write = new LinearAlgebra.Complex32.Matrix[] { mat1, mat2, mat3, mat4 };

            var names = new[] { "mat1", "dense_matrix_2", "s1", "sparse2" };
            if (File.Exists("testc.mat"))
            {
                File.Delete("testc.mat");
            }

            var writer = new MatlabMatrixWriter("testc.mat");
            writer.WriteMatrices(write, names);
            writer.Dispose();

            var reader = new MatlabMatrixReader<Complex32>("testc.mat");
            var read = reader.ReadMatrices(names);

            Assert.AreEqual(write.Length, read.Count);

            for (var i = 0; i < write.Length; i++)
            {
                var w = write[i];
                var r = read[names[i]];

                Assert.AreEqual(w.RowCount, r.RowCount);
                Assert.AreEqual(w.ColumnCount, r.ColumnCount);
                Assert.IsTrue(w.Equals(r));
            }
        }
        /// <summary>
        /// Adds a scaled vector to another: <c>result = y + alpha*x</c>.
        /// </summary>
        /// <param name="y">The vector to update.</param>
        /// <param name="alpha">The value to scale <paramref name="x"/> by.</param>
        /// <param name="x">The vector to add to <paramref name="y"/>.</param>
        /// <param name="result">The result of the addition.</param>
        /// <remarks>This is similar to the AXPY BLAS routine.</remarks>
        public virtual void AddVectorToScaledVector(Complex32[] y, Complex32 alpha, Complex32[] x, Complex32[] result)
        {
            if (y == null)
            {
                throw new ArgumentNullException("y");
            }

            if (x == null)
            {
                throw new ArgumentNullException("x");
            }

            if (y.Length != x.Length)
            {
                throw new ArgumentException(Resources.ArgumentVectorsSameLength);
            }

            if (alpha.IsZero())
            {
                y.Copy(result);
            }
            else if (alpha.IsOne())
            {
                if (Control.ParallelizeOperation(x.Length))
                {
                    CommonParallel.For(0, y.Length, index => result[index] = y[index] + x[index]);
                }
                else
                {
                    for (var index = 0; index < x.Length; index++)
                    {
                        result[index] = y[index] + x[index];
                    }
                }
            }
            else
            {
                if (Control.ParallelizeOperation(x.Length))
                {
                    CommonParallel.For(0, y.Length, index => result[index] = y[index] + (alpha * x[index]));
                }
                else
                {
                    for (var index = 0; index < x.Length; index++)
                    {
                        result[index] = y[index] + (alpha * x[index]);
                    }
                }
            }
 
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="UserCholesky"/> class. This object will compute the
        /// Cholesky factorization when the constructor is called and cache it's factorization.
        /// </summary>
        /// <param name="matrix">The matrix to factor.</param>
        /// <exception cref="ArgumentNullException">If <paramref name="matrix"/> is <c>null</c>.</exception>
        /// <exception cref="ArgumentException">If <paramref name="matrix"/> is not a square matrix.</exception>
        /// <exception cref="ArgumentException">If <paramref name="matrix"/> is not positive definite.</exception>
        public UserCholesky(Matrix<Complex32> matrix)
        {
            if (matrix == null)
            {
                throw new ArgumentNullException("matrix");
            }

            if (matrix.RowCount != matrix.ColumnCount)
            {
                throw new ArgumentException(Resources.ArgumentMatrixSquare);
            }

            // Create a new matrix for the Cholesky factor, then perform factorization (while overwriting).
            CholeskyFactor = matrix.Clone();
            var tmpColumn = new Complex32[CholeskyFactor.RowCount];

            // Main loop - along the diagonal
            for (var ij = 0; ij < CholeskyFactor.RowCount; ij++)
            {
                // "Pivot" element
                var tmpVal = CholeskyFactor.At(ij, ij);

                if (tmpVal.Real > 0.0)
                {
                    tmpVal = tmpVal.SquareRoot();
                    CholeskyFactor.At(ij, ij, tmpVal);
                    tmpColumn[ij] = tmpVal;

                    // Calculate multipliers and copy to local column
                    // Current column, below the diagonal
                    for (var i = ij + 1; i < CholeskyFactor.RowCount; i++)
                    {
                        CholeskyFactor.At(i, ij, CholeskyFactor.At(i, ij) / tmpVal);
                        tmpColumn[i] = CholeskyFactor.At(i, ij);
                    }

                    // Remaining columns, below the diagonal
                    DoCholeskyStep(CholeskyFactor, CholeskyFactor.RowCount, ij + 1, CholeskyFactor.RowCount, tmpColumn, Control.NumberOfParallelWorkerThreads);
                }
                else
                {
                    throw new ArgumentException(Resources.ArgumentMatrixPositiveDefinite);
                }

                for (var i = ij + 1; i < CholeskyFactor.RowCount; i++)
                {
                    CholeskyFactor.At(ij, i, Complex32.Zero);
                }
            }
        }
        public void CanCreateDenseVectorFromArray()
        {
            var data = new Complex32[Data.Length];
            Array.Copy(Data, data, Data.Length);
            var vector = new DenseVector(data);

            for (var i = 0; i < data.Length; i++)
            {
                Assert.AreEqual(data[i], vector[i]);
            }

            vector[0] = new Complex32(10.0f, 1);
            Assert.AreEqual(new Complex32(10.0f, 1), data[0]);
        }
 public override Complex32 voltage(Node referenceNode, Complex32? W = null)
 {
     if (W == null || W.Value.IsZero())
     {
         if (referenceNode == Nodes[0])
             return new Complex32((float)Value, 0);
         return new Complex32((float)-Value, 0);
     }
     else {
         if (referenceNode == Nodes[0])
             return ACVoltage;
         return ACVoltage;
     
     }
 }
        public void CanMultiplyWithComplex(float real)
        {
            var value = new Complex32(real, 1.0f);
            var matrix = TestMatrices["Singular3x3"];
            var clone = matrix.Clone();
            clone = clone.Multiply(value);

            for (var i = 0; i < matrix.RowCount; i++)
            {
                for (var j = 0; j < matrix.ColumnCount; j++)
                {
                    Assert.AreEqual(matrix[i, j] * value, clone[i, j]);
                }
            }
        }
Beispiel #31
0
        /// <summary>
        /// Initializes a new instance of the <see cref="UserSvd"/> class. This object will compute the
        /// the singular value decomposition when the constructor is called and cache it's decomposition.
        /// </summary>
        /// <param name="matrix">The matrix to factor.</param>
        /// <param name="computeVectors">Compute the singular U and VT vectors or not.</param>
        /// <exception cref="ArgumentNullException">If <paramref name="matrix"/> is <c>null</c>.</exception>
        /// <exception cref="ArgumentException">If SVD algorithm failed to converge with matrix <paramref name="matrix"/>.</exception>
        public UserSvd(Matrix <Complex32> matrix, bool computeVectors)
        {
            if (matrix == null)
            {
                throw new ArgumentNullException("matrix");
            }

            ComputeVectors = computeVectors;
            var nm         = Math.Min(matrix.RowCount + 1, matrix.ColumnCount);
            var matrixCopy = matrix.Clone();

            VectorS  = matrixCopy.CreateVector(nm);
            MatrixU  = matrixCopy.CreateMatrix(matrixCopy.RowCount, matrixCopy.RowCount);
            MatrixVT = matrixCopy.CreateMatrix(matrixCopy.ColumnCount, matrixCopy.ColumnCount);

            const int Maxiter = 1000;
            var       e       = new Complex32[matrixCopy.ColumnCount];
            var       work    = new Complex32[matrixCopy.RowCount];

            int       i, j;
            int       l, lp1;
            var       cs = 0.0f;
            var       sn = 0.0f;
            Complex32 t;

            var ncu = matrixCopy.RowCount;

            // Reduce matrixCopy to bidiagonal form, storing the diagonal elements
            // In s and the super-diagonal elements in e.
            var nct = Math.Min(matrixCopy.RowCount - 1, matrixCopy.ColumnCount);
            var nrt = Math.Max(0, Math.Min(matrixCopy.ColumnCount - 2, matrixCopy.RowCount));
            var lu  = Math.Max(nct, nrt);

            for (l = 0; l < lu; l++)
            {
                lp1 = l + 1;
                if (l < nct)
                {
                    // Compute the transformation for the l-th column and place the l-th diagonal in VectorS[l].
                    VectorS[l] = Cnrm2Column(matrixCopy, matrixCopy.RowCount, l, l);
                    if (VectorS[l].Magnitude != 0.0f)
                    {
                        if (matrixCopy.At(l, l).Magnitude != 0.0f)
                        {
                            VectorS[l] = Csign(VectorS[l], matrixCopy.At(l, l));
                        }

                        CscalColumn(matrixCopy, matrixCopy.RowCount, l, l, 1.0f / VectorS[l]);
                        matrixCopy.At(l, l, (Complex32.One + matrixCopy.At(l, l)));
                    }

                    VectorS[l] = -VectorS[l];
                }

                for (j = lp1; j < matrixCopy.ColumnCount; j++)
                {
                    if (l < nct)
                    {
                        if (VectorS[l].Magnitude != 0.0f)
                        {
                            // Apply the transformation.
                            t = -Cdotc(matrixCopy, matrixCopy.RowCount, l, j, l) / matrixCopy.At(l, l);
                            if (t != Complex32.Zero)
                            {
                                for (var ii = l; ii < matrixCopy.RowCount; ii++)
                                {
                                    matrixCopy.At(ii, j, matrixCopy.At(ii, j) + (t * matrixCopy.At(ii, l)));
                                }
                            }
                        }
                    }

                    // Place the l-th row of matrixCopy into  e for the
                    // Subsequent calculation of the row transformation.
                    e[j] = matrixCopy.At(l, j).Conjugate();
                }

                if (ComputeVectors && l < nct)
                {
                    // Place the transformation in u for subsequent back multiplication.
                    for (i = l; i < matrixCopy.RowCount; i++)
                    {
                        MatrixU.At(i, l, matrixCopy.At(i, l));
                    }
                }

                if (l >= nrt)
                {
                    continue;
                }

                // Compute the l-th row transformation and place the l-th super-diagonal in e(l).
                var enorm = Cnrm2Vector(e, lp1);
                e[l] = enorm;
                if (e[l].Magnitude != 0.0f)
                {
                    if (e[lp1].Magnitude != 0.0f)
                    {
                        e[l] = Csign(e[l], e[lp1]);
                    }

                    CscalVector(e, lp1, 1.0f / e[l]);
                    e[lp1] = Complex32.One + e[lp1];
                }

                e[l] = -e[l].Conjugate();
                if (lp1 < matrixCopy.RowCount && e[l].Magnitude != 0.0f)
                {
                    // Apply the transformation.
                    for (i = lp1; i < matrixCopy.RowCount; i++)
                    {
                        work[i] = Complex32.Zero;
                    }

                    for (j = lp1; j < matrixCopy.ColumnCount; j++)
                    {
                        if (e[j] != Complex32.Zero)
                        {
                            for (var ii = lp1; ii < matrixCopy.RowCount; ii++)
                            {
                                work[ii] += e[j] * matrixCopy.At(ii, j);
                            }
                        }
                    }

                    for (j = lp1; j < matrixCopy.ColumnCount; j++)
                    {
                        var ww = (-e[j] / e[lp1]).Conjugate();
                        if (ww != Complex32.Zero)
                        {
                            for (var ii = lp1; ii < matrixCopy.RowCount; ii++)
                            {
                                matrixCopy.At(ii, j, matrixCopy.At(ii, j) + (ww * work[ii]));
                            }
                        }
                    }
                }

                if (ComputeVectors)
                {
                    // Place the transformation in v for subsequent back multiplication.
                    for (i = lp1; i < matrixCopy.ColumnCount; i++)
                    {
                        MatrixVT.At(i, l, e[i]);
                    }
                }
            }

            // Set up the final bidiagonal matrixCopy or order m.
            var m     = Math.Min(matrixCopy.ColumnCount, matrixCopy.RowCount + 1);
            var nctp1 = nct + 1;
            var nrtp1 = nrt + 1;

            if (nct < matrixCopy.ColumnCount)
            {
                VectorS[nctp1 - 1] = matrixCopy.At((nctp1 - 1), (nctp1 - 1));
            }

            if (matrixCopy.RowCount < m)
            {
                VectorS[m - 1] = Complex32.Zero;
            }

            if (nrtp1 < m)
            {
                e[nrtp1 - 1] = matrixCopy.At((nrtp1 - 1), (m - 1));
            }

            e[m - 1] = Complex32.Zero;

            // If required, generate u.
            if (ComputeVectors)
            {
                for (j = nctp1 - 1; j < ncu; j++)
                {
                    for (i = 0; i < matrixCopy.RowCount; i++)
                    {
                        MatrixU.At(i, j, Complex32.Zero);
                    }

                    MatrixU.At(j, j, Complex32.One);
                }

                for (l = nct - 1; l >= 0; l--)
                {
                    if (VectorS[l].Magnitude != 0.0f)
                    {
                        for (j = l + 1; j < ncu; j++)
                        {
                            t = -Cdotc(MatrixU, matrixCopy.RowCount, l, j, l) / MatrixU.At(l, l);
                            if (t != Complex32.Zero)
                            {
                                for (var ii = l; ii < matrixCopy.RowCount; ii++)
                                {
                                    MatrixU.At(ii, j, MatrixU.At(ii, j) + (t * MatrixU.At(ii, l)));
                                }
                            }
                        }

                        CscalColumn(MatrixU, matrixCopy.RowCount, l, l, -1.0f);
                        MatrixU.At(l, l, Complex32.One + MatrixU.At(l, l));
                        for (i = 0; i < l; i++)
                        {
                            MatrixU.At(i, l, Complex32.Zero);
                        }
                    }
                    else
                    {
                        for (i = 0; i < matrixCopy.RowCount; i++)
                        {
                            MatrixU.At(i, l, Complex32.Zero);
                        }

                        MatrixU.At(l, l, Complex32.One);
                    }
                }
            }

            // If it is required, generate v.
            if (ComputeVectors)
            {
                for (l = matrixCopy.ColumnCount - 1; l >= 0; l--)
                {
                    lp1 = l + 1;
                    if (l < nrt)
                    {
                        if (e[l].Magnitude != 0.0f)
                        {
                            for (j = lp1; j < matrixCopy.ColumnCount; j++)
                            {
                                t = -Cdotc(MatrixVT, matrixCopy.ColumnCount, l, j, lp1) / MatrixVT.At(lp1, l);
                                if (t != Complex32.Zero)
                                {
                                    for (var ii = l; ii < matrixCopy.ColumnCount; ii++)
                                    {
                                        MatrixVT.At(ii, j, MatrixVT.At(ii, j) + (t * MatrixVT.At(ii, l)));
                                    }
                                }
                            }
                        }
                    }

                    for (i = 0; i < matrixCopy.ColumnCount; i++)
                    {
                        MatrixVT.At(i, l, Complex32.Zero);
                    }

                    MatrixVT.At(l, l, Complex32.One);
                }
            }

            // Transform s and e so that they are real .
            for (i = 0; i < m; i++)
            {
                Complex32 r;
                if (VectorS[i].Magnitude != 0.0f)
                {
                    t          = VectorS[i].Magnitude;
                    r          = VectorS[i] / t;
                    VectorS[i] = t;
                    if (i < m - 1)
                    {
                        e[i] = e[i] / r;
                    }

                    if (ComputeVectors)
                    {
                        CscalColumn(MatrixU, matrixCopy.RowCount, i, 0, r);
                    }
                }

                // Exit
                if (i == m - 1)
                {
                    break;
                }

                if (e[i].Magnitude != 0.0f)
                {
                    t              = e[i].Magnitude;
                    r              = t / e[i];
                    e[i]           = t;
                    VectorS[i + 1] = VectorS[i + 1] * r;
                    if (ComputeVectors)
                    {
                        CscalColumn(MatrixVT, matrixCopy.ColumnCount, i + 1, 0, r);
                    }
                }
            }

            // Main iteration loop for the singular values.
            var mn   = m;
            var iter = 0;

            while (m > 0)
            {
                // Quit if all the singular values have been found. If too many iterations have been performed,
                // throw exception that Convergence Failed
                if (iter >= Maxiter)
                {
                    throw new ArgumentException(Resources.ConvergenceFailed);
                }

                // This section of the program inspects for negligible elements in the s and e arrays. On
                // completion the variables kase and l are set as follows.
                // Kase = 1     if VectorS[m] and e[l-1] are negligible and l < m
                // Kase = 2     if VectorS[l] is negligible and l < m
                // Kase = 3     if e[l-1] is negligible, l < m, and VectorS[l, ..., VectorS[m] are not negligible (qr step).
                // Лase = 4     if e[m-1] is negligible (convergence).
                float ztest;
                float test;
                for (l = m - 2; l >= 0; l--)
                {
                    test  = VectorS[l].Magnitude + VectorS[l + 1].Magnitude;
                    ztest = test + e[l].Magnitude;
                    if (ztest.AlmostEqualInDecimalPlaces(test, 7))
                    {
                        e[l] = Complex32.Zero;
                        break;
                    }
                }

                int kase;
                if (l == m - 2)
                {
                    kase = 4;
                }
                else
                {
                    int ls;
                    for (ls = m - 1; ls > l; ls--)
                    {
                        test = 0.0f;
                        if (ls != m - 1)
                        {
                            test = test + e[ls].Magnitude;
                        }

                        if (ls != l + 1)
                        {
                            test = test + e[ls - 1].Magnitude;
                        }

                        ztest = test + VectorS[ls].Magnitude;
                        if (ztest.AlmostEqualInDecimalPlaces(test, 7))
                        {
                            VectorS[ls] = Complex32.Zero;
                            break;
                        }
                    }

                    if (ls == l)
                    {
                        kase = 3;
                    }
                    else if (ls == m - 1)
                    {
                        kase = 1;
                    }
                    else
                    {
                        kase = 2;
                        l    = ls;
                    }
                }

                l = l + 1;

                // Perform the task indicated by kase.
                int   k;
                float f;
                switch (kase)
                {
                // Deflate negligible VectorS[m].
                case 1:
                    f        = e[m - 2].Real;
                    e[m - 2] = Complex32.Zero;
                    float t1;
                    for (var kk = l; kk < m - 1; kk++)
                    {
                        k  = m - 2 - kk + l;
                        t1 = VectorS[k].Real;
                        Srotg(ref t1, ref f, ref cs, ref sn);
                        VectorS[k] = t1;
                        if (k != l)
                        {
                            f        = -sn * e[k - 1].Real;
                            e[k - 1] = cs * e[k - 1];
                        }

                        if (ComputeVectors)
                        {
                            Csrot(MatrixVT, matrixCopy.ColumnCount, k, m - 1, cs, sn);
                        }
                    }

                    break;

                // Split at negligible VectorS[l].
                case 2:
                    f        = e[l - 1].Real;
                    e[l - 1] = Complex32.Zero;
                    for (k = l; k < m; k++)
                    {
                        t1 = VectorS[k].Real;
                        Srotg(ref t1, ref f, ref cs, ref sn);
                        VectorS[k] = t1;
                        f          = -sn * e[k].Real;
                        e[k]       = cs * e[k];
                        if (ComputeVectors)
                        {
                            Csrot(MatrixU, matrixCopy.RowCount, k, l - 1, cs, sn);
                        }
                    }

                    break;

                // Perform one qr step.
                case 3:
                    // Calculate the shift.
                    var scale = 0.0f;
                    scale = Math.Max(scale, VectorS[m - 1].Magnitude);
                    scale = Math.Max(scale, VectorS[m - 2].Magnitude);
                    scale = Math.Max(scale, e[m - 2].Magnitude);
                    scale = Math.Max(scale, VectorS[l].Magnitude);
                    scale = Math.Max(scale, e[l].Magnitude);
                    var sm    = VectorS[m - 1].Real / scale;
                    var smm1  = VectorS[m - 2].Real / scale;
                    var emm1  = e[m - 2].Real / scale;
                    var sl    = VectorS[l].Real / scale;
                    var el    = e[l].Real / scale;
                    var b     = (((smm1 + sm) * (smm1 - sm)) + (emm1 * emm1)) / 2.0f;
                    var c     = (sm * emm1) * (sm * emm1);
                    var shift = 0.0f;

                    if (b != 0.0f || c != 0.0f)
                    {
                        shift = (float)Math.Sqrt((b * b) + c);
                        if (b < 0.0f)
                        {
                            shift = -shift;
                        }

                        shift = c / (b + shift);
                    }

                    f = ((sl + sm) * (sl - sm)) + shift;
                    var g = sl * el;

                    // Chase zeros.
                    for (k = l; k < m - 1; k++)
                    {
                        Srotg(ref f, ref g, ref cs, ref sn);
                        if (k != l)
                        {
                            e[k - 1] = f;
                        }

                        f              = (cs * VectorS[k].Real) + (sn * e[k].Real);
                        e[k]           = (cs * e[k]) - (sn * VectorS[k]);
                        g              = sn * VectorS[k + 1].Real;
                        VectorS[k + 1] = cs * VectorS[k + 1];
                        if (ComputeVectors)
                        {
                            Csrot(MatrixVT, matrixCopy.ColumnCount, k, k + 1, cs, sn);
                        }

                        Srotg(ref f, ref g, ref cs, ref sn);
                        VectorS[k]     = f;
                        f              = (cs * e[k].Real) + (sn * VectorS[k + 1].Real);
                        VectorS[k + 1] = (-sn * e[k]) + (cs * VectorS[k + 1]);
                        g              = sn * e[k + 1].Real;
                        e[k + 1]       = cs * e[k + 1];
                        if (ComputeVectors && k < matrixCopy.RowCount)
                        {
                            Csrot(MatrixU, matrixCopy.RowCount, k, k + 1, cs, sn);
                        }
                    }

                    e[m - 2] = f;
                    iter     = iter + 1;
                    break;

                // Convergence.
                case 4:
                    // Make the singular value  positive
                    if (VectorS[l].Real < 0.0f)
                    {
                        VectorS[l] = -VectorS[l];
                        if (ComputeVectors)
                        {
                            CscalColumn(MatrixVT, matrixCopy.ColumnCount, l, 0, -1.0f);
                        }
                    }

                    // Order the singular value.
                    while (l != mn - 1)
                    {
                        if (VectorS[l].Real >= VectorS[l + 1].Real)
                        {
                            break;
                        }

                        t              = VectorS[l];
                        VectorS[l]     = VectorS[l + 1];
                        VectorS[l + 1] = t;
                        if (ComputeVectors && l < matrixCopy.ColumnCount)
                        {
                            Swap(MatrixVT, matrixCopy.ColumnCount, l, l + 1);
                        }

                        if (ComputeVectors && l < matrixCopy.RowCount)
                        {
                            Swap(MatrixU, matrixCopy.RowCount, l, l + 1);
                        }

                        l = l + 1;
                    }

                    iter = 0;
                    m    = m - 1;
                    break;
                }
            }

            if (ComputeVectors)
            {
                MatrixVT = MatrixVT.ConjugateTranspose();
            }

            // Adjust the size of s if rows < columns. We are using ported copy of linpack's svd code and it uses
            // a singular vector of length mRows+1 when mRows < mColumns. The last element is not used and needs to be removed.
            // we should port lapack's svd routine to remove this problem.
            if (matrixCopy.RowCount < matrixCopy.ColumnCount)
            {
                nm--;
                var tmp = matrixCopy.CreateVector(nm);
                for (i = 0; i < nm; i++)
                {
                    tmp[i] = VectorS[i];
                }

                VectorS = tmp;
            }
        }
Beispiel #32
0
 /// <summary>
 /// Creates a <c>Complex32</c> number based on a string. The string can be in the
 /// following formats (without the quotes): 'n', 'ni', 'n +/- ni',
 /// 'ni +/- n', 'n,n', 'n,ni,' '(n,n)', or '(n,ni)', where n is a double.
 /// </summary>
 /// <returns>
 /// A complex number containing the value specified by the given string.
 /// </returns>
 /// <param name="value">
 /// the string to parse.
 /// </param>
 public static Complex32 ToComplex32(this string value)
 {
     return(Complex32.Parse(value));
 }
Beispiel #33
0
 /// <summary>
 /// Converts the string representation of a complex number to a single-precision complex number equivalent.
 /// A return value indicates whether the conversion succeeded or failed.
 /// </summary>
 /// <param name="value">
 /// A string containing a complex number to convert.
 /// </param>
 /// <param name="result">
 /// The parsed value.
 /// </param>
 /// <returns>
 /// If the conversion succeeds, the result will contain a complex number equivalent to value.
 /// Otherwise the result will contain complex32.Zero.  This parameter is passed uninitialized.
 /// </returns>
 public static bool TryToComplex32(this string value, out Complex32 result)
 {
     return(Complex32.TryParse(value, out result));
 }
Beispiel #34
0
 public DenseMatrix(int rows, int columns, Complex32 value)
     : this(DenseColumnMajorMatrixStorage <Complex32> .OfInit(rows, columns, (i, j) => value))
 {
 }
        public override void MatrixMultiplyWithUpdate(Transpose transposeA, Transpose transposeB, Complex32 alpha, Complex32[] a, int rowsA, int columnsA, Complex32[] b, int rowsB, int columnsB, Complex32 beta, Complex32[] c)
        {
            if (a == null)
            {
                throw new ArgumentNullException("a");
            }

            if (b == null)
            {
                throw new ArgumentNullException("b");
            }

            if (c == null)
            {
                throw new ArgumentNullException("c");
            }

            var m = transposeA == Transpose.DontTranspose ? rowsA : columnsA;
            var n = transposeB == Transpose.DontTranspose ? columnsB : rowsB;
            var k = transposeA == Transpose.DontTranspose ? columnsA : rowsA;
            var l = transposeB == Transpose.DontTranspose ? rowsB : columnsB;

            if (c.Length != m * n)
            {
                throw new ArgumentException(Resources.ArgumentMatrixDimensions);
            }

            if (k != l)
            {
                throw new ArgumentException(Resources.ArgumentMatrixDimensions);
            }

            SafeNativeMethods.c_matrix_multiply(_blasHandle, transposeA.ToCUDA(), transposeB.ToCUDA(), m, n, k, alpha, a, b, beta, c);
        }
Beispiel #36
0
        /// <summary>
        /// Solves a system of linear equations, <b>AX = B</b>, with A QR factorized.
        /// </summary>
        /// <param name="input">The right hand side <see cref="Matrix{T}"/>, <b>B</b>.</param>
        /// <param name="result">The left hand side <see cref="Matrix{T}"/>, <b>X</b>.</param>
        public override void Solve(Matrix <Complex32> input, Matrix <Complex32> result)
        {
            // Check for proper arguments.
            if (input == null)
            {
                throw new ArgumentNullException("input");
            }

            if (result == null)
            {
                throw new ArgumentNullException("result");
            }

            // The solution X should have the same number of columns as B
            if (input.ColumnCount != result.ColumnCount)
            {
                throw new ArgumentException(Resources.ArgumentMatrixSameColumnDimension);
            }

            // The dimension compatibility conditions for X = A\B require the two matrices A and B to have the same number of rows
            if (MatrixQ.RowCount != input.RowCount)
            {
                throw new ArgumentException(Resources.ArgumentMatrixSameRowDimension);
            }

            // The solution X row dimension is equal to the column dimension of A
            if (MatrixQ.ColumnCount != result.RowCount)
            {
                throw new ArgumentException(Resources.ArgumentMatrixSameColumnDimension);
            }

            var inputCopy = input.Clone();

            // Compute Y = transpose(Q)*B
            var column = new Complex32[MatrixQ.RowCount];

            for (var j = 0; j < input.ColumnCount; j++)
            {
                for (var k = 0; k < MatrixQ.RowCount; k++)
                {
                    column[k] = inputCopy.At(k, j);
                }

                for (var i = 0; i < MatrixQ.ColumnCount; i++)
                {
                    var s = Complex32.Zero;
                    for (var k = 0; k < MatrixQ.RowCount; k++)
                    {
                        s += MatrixQ.At(k, i).Conjugate() * column[k];
                    }

                    inputCopy.At(i, j, s);
                }
            }

            // Solve R*X = Y;
            for (var k = MatrixQ.ColumnCount - 1; k >= 0; k--)
            {
                for (var j = 0; j < input.ColumnCount; j++)
                {
                    inputCopy.At(k, j, inputCopy.At(k, j) / MatrixR.At(k, k));
                }

                for (var i = 0; i < k; i++)
                {
                    for (var j = 0; j < input.ColumnCount; j++)
                    {
                        inputCopy.At(i, j, inputCopy.At(i, j) - (inputCopy.At(k, j) * MatrixR.At(i, k)));
                    }
                }
            }

            for (var i = 0; i < MatrixR.ColumnCount; i++)
            {
                for (var j = 0; j < input.ColumnCount; j++)
                {
                    result.At(i, j, inputCopy.At(i, j));
                }
            }
        }
Beispiel #37
0
 /// <summary>
 /// Initializes a new instance of the <see cref="DenseVector"/> class with a given size.
 /// </summary>
 /// <param name="size">
 /// the size of the vector.
 /// </param>
 /// <exception cref="ArgumentException">
 /// If <paramref name="size"/> is less than one.
 /// </exception>
 public DenseVector(int size) : base(size)
 {
     Data = new Complex32[size];
 }
Beispiel #38
0
 internal static extern void c_scale(IntPtr blasHandle, int n, Complex32 alpha, [In, Out] Complex32[] x);
Beispiel #39
0
        /// <summary>
        /// Solves a system of linear equations, <b>Ax = b</b>, with A QR factorized.
        /// </summary>
        /// <param name="input">The right hand side vector, <b>b</b>.</param>
        /// <param name="result">The left hand side <see cref="Matrix{T}"/>, <b>x</b>.</param>
        public override void Solve(Vector <Complex32> input, Vector <Complex32> result)
        {
            if (input == null)
            {
                throw new ArgumentNullException("input");
            }

            if (result == null)
            {
                throw new ArgumentNullException("result");
            }

            // Ax=b where A is an m x n matrix
            // Check that b is a column vector with m entries
            if (MatrixQ.RowCount != input.Count)
            {
                throw new ArgumentException(Resources.ArgumentVectorsSameLength);
            }

            // Check that x is a column vector with n entries
            if (MatrixQ.ColumnCount != result.Count)
            {
                throw Matrix.DimensionsDontMatch <ArgumentException>(MatrixQ, result);
            }

            var inputCopy = input.Clone();

            // Compute Y = transpose(Q)*B
            var column = new Complex32[MatrixQ.RowCount];

            for (var k = 0; k < MatrixQ.RowCount; k++)
            {
                column[k] = inputCopy[k];
            }

            for (var i = 0; i < MatrixQ.ColumnCount; i++)
            {
                var s = Complex32.Zero;
                for (var k = 0; k < MatrixQ.RowCount; k++)
                {
                    s += MatrixQ.At(k, i).Conjugate() * column[k];
                }

                inputCopy[i] = s;
            }

            // Solve R*X = Y;
            for (var k = MatrixQ.ColumnCount - 1; k >= 0; k--)
            {
                inputCopy[k] /= MatrixR.At(k, k);
                for (var i = 0; i < k; i++)
                {
                    inputCopy[i] -= inputCopy[k] * MatrixR.At(i, k);
                }
            }

            for (var i = 0; i < MatrixR.ColumnCount; i++)
            {
                result[i] = inputCopy[i];
            }
        }
Beispiel #40
0
 internal static extern void c_axpy(IntPtr blasHandle, int n, Complex32 alpha, Complex32[] x, [In, Out] Complex32[] y);
Beispiel #41
0
 internal static extern void c_matrix_multiply(IntPtr blasHandle, int transA, int transB, int m, int n, int k, Complex32 alpha, Complex32[] x, Complex32[] y, Complex32 beta, [In, Out] Complex32[] c);
Beispiel #42
0
        /// <summary>
        /// Solves a system of linear equations, <b>AX = B</b>, with A SVD factorized.
        /// </summary>
        /// <param name="input">The right hand side <see cref="Matrix{T}"/>, <b>B</b>.</param>
        /// <param name="result">The left hand side <see cref="Matrix{T}"/>, <b>X</b>.</param>
        public override void Solve(Matrix <Complex32> input, Matrix <Complex32> result)
        {
            // Check for proper arguments.
            if (input == null)
            {
                throw new ArgumentNullException("input");
            }

            if (result == null)
            {
                throw new ArgumentNullException("result");
            }

            if (!ComputeVectors)
            {
                throw new InvalidOperationException(Resources.SingularVectorsNotComputed);
            }

            // The solution X should have the same number of columns as B
            if (input.ColumnCount != result.ColumnCount)
            {
                throw new ArgumentException(Resources.ArgumentMatrixSameColumnDimension);
            }

            // The dimension compatibility conditions for X = A\B require the two matrices A and B to have the same number of rows
            if (MatrixU.RowCount != input.RowCount)
            {
                throw new ArgumentException(Resources.ArgumentMatrixSameRowDimension);
            }

            // The solution X row dimension is equal to the column dimension of A
            if (MatrixVT.ColumnCount != result.RowCount)
            {
                throw new ArgumentException(Resources.ArgumentMatrixSameColumnDimension);
            }

            var mn = Math.Min(MatrixU.RowCount, MatrixVT.ColumnCount);
            var bn = input.ColumnCount;

            var tmp = new Complex32[MatrixVT.ColumnCount];

            for (var k = 0; k < bn; k++)
            {
                for (var j = 0; j < MatrixVT.ColumnCount; j++)
                {
                    var value = Complex32.Zero;
                    if (j < mn)
                    {
                        for (var i = 0; i < MatrixU.RowCount; i++)
                        {
                            value += MatrixU.At(i, j).Conjugate() * input.At(i, k);
                        }

                        value /= VectorS[j];
                    }

                    tmp[j] = value;
                }

                for (var j = 0; j < MatrixVT.ColumnCount; j++)
                {
                    var value = Complex32.Zero;
                    for (var i = 0; i < MatrixVT.ColumnCount; i++)
                    {
                        value += MatrixVT.At(i, j).Conjugate() * tmp[i];
                    }

                    result[j, k] = value;
                }
            }
        }
Beispiel #43
0
 /// <summary>
 /// Create a new sparse vector and initialize each value using the provided value.
 /// </summary>
 public static SparseVector Create(int length, Complex32 value)
 {
     return(new SparseVector(SparseVectorStorage <Complex32> .OfValue(length, value)));
 }
Beispiel #44
0
        public override void MatrixMultiplyWithUpdate(Transpose transposeA, Transpose transposeB, Complex32 alpha, Complex32[] a, int rowsA, int columnsA, Complex32[] b, int rowsB, int columnsB, Complex32 beta, Complex32[] c)
        {
            if (a == null)
            {
                throw new ArgumentNullException(nameof(a));
            }

            if (b == null)
            {
                throw new ArgumentNullException(nameof(b));
            }

            if (c == null)
            {
                throw new ArgumentNullException(nameof(c));
            }

            var m = transposeA == Transpose.DontTranspose ? rowsA : columnsA;
            var n = transposeB == Transpose.DontTranspose ? columnsB : rowsB;
            var k = transposeA == Transpose.DontTranspose ? columnsA : rowsA;
            var l = transposeB == Transpose.DontTranspose ? rowsB : columnsB;

            if (c.Length != m * n)
            {
                throw new ArgumentException("Matrix dimensions must agree.");
            }

            if (k != l)
            {
                throw new ArgumentException("Matrix dimensions must agree.");
            }

            SafeNativeMethods.c_matrix_multiply(transposeA, transposeB, m, n, k, alpha, a, b, beta, c);
        }
Beispiel #45
0
        /// <summary>
        /// Creates a Complex32 dense vector based on a string. The string can be in the following formats (without the
        /// quotes): 'n', 'n;n;..', '(n;n;..)', '[n;n;...]', where n is a double.
        /// </summary>
        /// <returns>
        /// A Complex32 dense vector containing the values specified by the given string.
        /// </returns>
        /// <param name="value">
        /// the string to parse.
        /// </param>
        /// <param name="formatProvider">
        /// An <see cref="IFormatProvider"/> that supplies culture-specific formatting information.
        /// </param>
        public static DenseVector Parse(string value, IFormatProvider formatProvider)
        {
            if (value == null)
            {
                throw new ArgumentNullException("value");
            }

            value = value.Trim();
            if (value.Length == 0)
            {
                throw new FormatException();
            }

            // strip out parens
            if (value.StartsWith("(", StringComparison.Ordinal))
            {
                if (!value.EndsWith(")", StringComparison.Ordinal))
                {
                    throw new FormatException();
                }

                value = value.Substring(1, value.Length - 2).Trim();
            }

            if (value.StartsWith("[", StringComparison.Ordinal))
            {
                if (!value.EndsWith("]", StringComparison.Ordinal))
                {
                    throw new FormatException();
                }

                value = value.Substring(1, value.Length - 2).Trim();
            }

            // keywords
            var textInfo = formatProvider.GetTextInfo();
            var keywords = new[] { textInfo.ListSeparator };

            // lexing
            var tokens = new LinkedList <string>();

            GlobalizationHelper.Tokenize(tokens.AddFirst(value), keywords, 0);
            var token = tokens.First;

            if (token == null || tokens.Count.IsEven())
            {
                throw new FormatException();
            }

            // parsing
            var data = new Complex32[(tokens.Count + 1) >> 1];

            for (var i = 0; i < data.Length; i++)
            {
                if (token == null || token.Value == textInfo.ListSeparator)
                {
                    throw new FormatException();
                }

                data[i] = token.Value.ToComplex32(formatProvider);

                token = token.Next;
                if (token != null)
                {
                    token = token.Next;
                }
            }

            return(new DenseVector(data));
        }
Beispiel #46
0
        public override void QRSolve(Complex32[] a, int rows, int columns, Complex32[] b, int columnsB, Complex32[] x, QRMethod method = QRMethod.Full)
        {
            var work = new Complex32[columns * Control.BlockSize];

            QRSolve(a, rows, columns, b, columnsB, x, work, method);
        }
Beispiel #47
0
 /// <summary>Sets the <paramref name="value"/> at the given <paramref name="index"/>.</summary>
 /// <param name="index">The index of the value to get or set.</param>
 /// <param name="value">The value to set.</param>
 internal protected override void At(int index, Complex32 value)
 {
     Data[index] = value;
 }
Beispiel #48
0
        /// <summary>
        /// Solves the matrix equation Ax = b, where A is the coefficient matrix, b is the
        /// solution vector and x is the unknown vector.
        /// </summary>
        /// <param name="matrix">The coefficient matrix, <c>A</c>.</param>
        /// <param name="input">The solution vector, <c>b</c></param>
        /// <param name="result">The result vector, <c>x</c></param>
        public void Solve(Matrix matrix, Vector input, Vector result)
        {
            // If we were stopped before, we are no longer
            // We're doing this at the start of the method to ensure
            // that we can use these fields immediately.
            _hasBeenStopped = false;

            // Error checks
            if (matrix == null)
            {
                throw new ArgumentNullException("matrix");
            }

            if (matrix.RowCount != matrix.ColumnCount)
            {
                throw new ArgumentException(Resources.ArgumentMatrixSquare, "matrix");
            }

            if (input == null)
            {
                throw new ArgumentNullException("input");
            }

            if (result == null)
            {
                throw new ArgumentNullException("result");
            }

            if (result.Count != input.Count)
            {
                throw new ArgumentException(Resources.ArgumentVectorsSameLength);
            }

            if (input.Count != matrix.RowCount)
            {
                throw new ArgumentException(Resources.ArgumentMatrixDimensions);
            }

            // Initialize the solver fields
            // Set the convergence monitor
            if (_iterator == null)
            {
                _iterator = Iterator.CreateDefault();
            }

            if (_preconditioner == null)
            {
                _preconditioner = new UnitPreconditioner();
            }

            _preconditioner.Initialize(matrix);

            var d = new DenseVector(input.Count);
            var r = new DenseVector(input);

            var uodd  = new DenseVector(input.Count);
            var ueven = new DenseVector(input.Count);

            var v = new DenseVector(input.Count);
            var pseudoResiduals = new DenseVector(input);

            var x     = new DenseVector(input.Count);
            var yodd  = new DenseVector(input.Count);
            var yeven = new DenseVector(input);

            // Temp vectors
            var temp  = new DenseVector(input.Count);
            var temp1 = new DenseVector(input.Count);
            var temp2 = new DenseVector(input.Count);

            // Initialize
            var startNorm = input.Norm(2);

            // Define the scalars
            Complex32 alpha = 0;
            Complex32 eta   = 0;
            float     theta = 0;

            var       tau = startNorm.Real;
            Complex32 rho = tau * tau;

            // Calculate the initial values for v
            // M temp = yEven
            _preconditioner.Approximate(yeven, temp);

            // v = A temp
            matrix.Multiply(temp, v);

            // Set uOdd
            v.CopyTo(ueven);

            // Start the iteration
            var iterationNumber = 0;

            while (ShouldContinue(iterationNumber, result, input, pseudoResiduals))
            {
                // First part of the step, the even bit
                if (IsEven(iterationNumber))
                {
                    // sigma = (v, r)
                    var sigma = v.DotProduct(r.Conjugate());
                    if (sigma.Real.AlmostEqual(0, 1) && sigma.Imaginary.AlmostEqual(0, 1))
                    {
                        // FAIL HERE
                        _iterator.IterationCancelled();
                        break;
                    }

                    // alpha = rho / sigma
                    alpha = rho / sigma;

                    // yOdd = yEven - alpha * v
                    v.Multiply(-alpha, temp1);
                    yeven.Add(temp1, yodd);

                    // Solve M temp = yOdd
                    _preconditioner.Approximate(yodd, temp);

                    // uOdd = A temp
                    matrix.Multiply(temp, uodd);
                }

                // The intermediate step which is equal for both even and
                // odd iteration steps.
                // Select the correct vector
                var uinternal = IsEven(iterationNumber) ? ueven : uodd;
                var yinternal = IsEven(iterationNumber) ? yeven : yodd;

                // pseudoResiduals = pseudoResiduals - alpha * uOdd
                uinternal.Multiply(-alpha, temp1);
                pseudoResiduals.Add(temp1, temp2);
                temp2.CopyTo(pseudoResiduals);

                // d = yOdd + theta * theta * eta / alpha * d
                d.Multiply(theta * theta * eta / alpha, temp);
                yinternal.Add(temp, d);

                // theta = ||pseudoResiduals||_2 / tau
                theta = pseudoResiduals.Norm(2).Real / tau;
                var c = 1 / (float)Math.Sqrt(1 + (theta * theta));

                // tau = tau * theta * c
                tau *= theta * c;

                // eta = c^2 * alpha
                eta = c * c * alpha;

                // x = x + eta * d
                d.Multiply(eta, temp1);
                x.Add(temp1, temp2);
                temp2.CopyTo(x);

                // Check convergence and see if we can bail
                if (!ShouldContinue(iterationNumber, result, input, pseudoResiduals))
                {
                    // Calculate the real values
                    _preconditioner.Approximate(x, result);

                    // Calculate the true residual. Use the temp vector for that
                    // so that we don't pollute the pseudoResidual vector for no
                    // good reason.
                    CalculateTrueResidual(matrix, temp, result, input);

                    // Now recheck the convergence
                    if (!ShouldContinue(iterationNumber, result, input, temp))
                    {
                        // We're all good now.
                        return;
                    }
                }

                // The odd step
                if (!IsEven(iterationNumber))
                {
                    if (rho.Real.AlmostEqual(0, 1) && rho.Imaginary.AlmostEqual(0, 1))
                    {
                        // FAIL HERE
                        _iterator.IterationCancelled();
                        break;
                    }

                    var rhoNew = pseudoResiduals.DotProduct(r.Conjugate());
                    var beta   = rhoNew / rho;

                    // Update rho for the next loop
                    rho = rhoNew;

                    // yOdd = pseudoResiduals + beta * yOdd
                    yodd.Multiply(beta, temp1);
                    pseudoResiduals.Add(temp1, yeven);

                    // Solve M temp = yOdd
                    _preconditioner.Approximate(yeven, temp);

                    // uOdd = A temp
                    matrix.Multiply(temp, ueven);

                    // v = uEven + beta * (uOdd + beta * v)
                    v.Multiply(beta, temp1);
                    uodd.Add(temp1, temp);

                    temp.Multiply(beta, temp1);
                    ueven.Add(temp1, v);
                }

                // Calculate the real values
                _preconditioner.Approximate(x, result);

                iterationNumber++;
            }
        }
Beispiel #49
0
        public override void QRSolveFactored(Complex32[] q, Complex32[] r, int rowsR, int columnsR, Complex32[] tau, Complex32[] b, int columnsB, Complex32[] x, QRMethod method = QRMethod.Full)
        {
            var work = new Complex32[columnsR * Control.BlockSize];

            QRSolveFactored(q, r, rowsR, columnsR, tau, b, columnsB, x, work, method);
        }
Beispiel #50
0
 /// <summary>
 /// Calculates absolute value of <paramref name="z1"/> multiplied on signum function of <paramref name="z2"/>
 /// </summary>
 /// <param name="z1">Complex32 value z1</param>
 /// <param name="z2">Complex32 value z2</param>
 /// <returns>Result multiplication of signum function and absolute value</returns>
 private static Complex32 Csign(Complex32 z1, Complex32 z2)
 {
     return(z1.Magnitude * (z2 / z2.Magnitude));
 }
Beispiel #51
0
        private void Capture(AudioCapturedEventArgs e)
        {
            DataUtils.Normalize(e.Left.Buffer);
            DataUtils.Normalize(e.Right.Buffer);

            var a      = new Complex32[e.Left.Buffer.Length];
            var b      = new Complex32[e.Right.Buffer.Length];
            var sp1    = new Complex32[a.Length];
            var sp2    = new Complex32[b.Length];
            var window = Window.Hamming(a.Length);


            // Составляем комплексный массив и умножаем на окно Хэмминга
            for (int i = 0; i < a.Length; i++)
            {
                a[i] = new Complex32(e.Left.Buffer[i] * (float)window[i], 0);
                b[i] = new Complex32(e.Left.Buffer[i] * (float)window[i], 0);
            }

            // Преобразование фурье
            Fourier.Forward(a);
            Fourier.Forward(b);
            Array.Copy(a, sp1, a.Length);
            Array.Copy(b, sp2, b.Length);

            // Поэлементно умножаем первое на сопряженное ко второму
            for (int i = 0; i < a.Length; i++)
            {
                a[i] = a[i] * b[i].Conjugate();
            }


            // Поэлементно делим на модуль самого себя
            //for (int i = 0; i < a.Length; i++)
            //    a[i] = Complex32.Divide(a[i], a[i].Magnitude);

            //Fourier.Inverse(a);

            // Поиск максимума

            /*int maxI = 0;
             * float max = a[0].Imaginary;
             * for (int i = 0; i < a.Length; i++)
             * {
             *  if (Math.Abs(a[i].Imaginary) > max)
             *  {
             *      maxI = i;
             *      max = Math.Abs(a[i].Imaginary);
             *  }
             * }*/

            sgraphWave.Clear();
            sgraphSpectrum.Clear();

            for (int i = 0; i < e.Left.Buffer.Length; i++)
            {
                sgraphWave.AddData(i, e.Left.Buffer[i], e.Right.Buffer[i]);
            }

            for (int i = 0; i < a.Length / 10; i++)
            {
                float hz = i * e.Left.Source.WaveFormat.SampleRate / (float)a.Length;
                //sgraphSpectrum.AddData(hz, sp1[i].Magnitude, sp2[i].Magnitude);
                sgraphSpectrum.AddData(hz, 0, a[i].Imaginary);
            }


            sgraphWave.UpdateGraph();
            sgraphSpectrum.UpdateGraph();
        }
 internal static extern void c_matrix_multiply(Transpose transA, Transpose transB, int m, int n, int k, Complex32 alpha, Complex32[] x, Complex32[] y, Complex32 beta, [In, Out] Complex32[] c);
Beispiel #53
0
 public void ParseThrowsFormatExceptionIfMissingClosingParen()
 {
     Assert.Throws <FormatException>(() => Complex32.Parse("(1,2"));
 }
 internal static extern void c_scale(int n, Complex32 alpha, [In, Out] Complex32[] x);
Beispiel #55
0
 /// <summary>
 /// Converts the string representation of a complex number to single-precision complex number equivalent.
 /// A return value indicates whether the conversion succeeded or failed.
 /// </summary>
 /// <param name="value">
 /// A string containing a complex number to convert.
 /// </param>
 /// <param name="formatProvider">
 /// An <see cref="IFormatProvider"/> that supplies culture-specific formatting information about value.
 /// </param>
 /// <param name="result">
 /// The parsed value.
 /// </param>
 /// <returns>
 /// If the conversion succeeds, the result will contain a complex number equivalent to value.
 /// Otherwise the result will contain Complex.Zero.  This parameter is passed uninitialized.
 /// </returns>
 public static bool TryToComplex32(this string value, IFormatProvider formatProvider, out Complex32 result)
 {
     return(Complex32.TryParse(value, formatProvider, out result));
 }
 internal static extern void c_axpy(int n, Complex32 alpha, Complex32[] x, [In, Out] Complex32[] y);
Beispiel #57
0
 /// <summary>
 /// Creates a <c>Complex32</c> number based on a string. The string can be in the
 /// following formats (without the quotes): 'n', 'ni', 'n +/- ni',
 /// 'ni +/- n', 'n,n', 'n,ni,' '(n,n)', or '(n,ni)', where n is a double.
 /// </summary>
 /// <returns>
 /// A complex number containing the value specified by the given string.
 /// </returns>
 /// <param name="value">
 /// the string to parse.
 /// </param>
 /// <param name="formatProvider">
 /// An <see cref="IFormatProvider"/> that supplies culture-specific
 /// formatting information.
 /// </param>
 public static Complex32 ToComplex32(this string value, IFormatProvider formatProvider)
 {
     return(Complex32.Parse(value, formatProvider));
 }
Beispiel #58
0
 /// <summary>
 /// Subtracts a scalar from each element of the vector and stores the result in the result vector.
 /// </summary>
 /// <param name="scalar">
 /// The scalar to subtract.
 /// </param>
 /// <param name="result">
 /// The vector to store the result of the subtraction.
 /// </param>
 protected override void DoSubtract(Complex32 scalar, Vector <Complex32> result)
 {
     DoAdd(-scalar, result);
 }
Beispiel #59
0
 /// <summary>
 /// Scale column <paramref name="column"/> by <paramref name="z"/> starting from row <paramref name="rowStart"/>
 /// </summary>
 /// <param name="a">Source matrix</param>
 /// <param name="rowCount">The number of rows in <paramref name="a"/> </param>
 /// <param name="column">Column to scale</param>
 /// <param name="rowStart">Row to scale from</param>
 /// <param name="z">Scale value</param>
 private static void CscalColumn(Matrix <Complex32> a, int rowCount, int column, int rowStart, Complex32 z)
 {
     for (var i = rowStart; i < rowCount; i++)
     {
         a.At(i, column, a.At(i, column) * z);
     }
 }
Beispiel #60
0
        /// <summary>
        /// Solves the matrix equation Ax = b, where A is the coefficient matrix, b is the
        /// solution vector and x is the unknown vector.
        /// </summary>
        /// <param name="matrix">The coefficient matrix, <c>A</c>.</param>
        /// <param name="input">The solution vector, <c>b</c></param>
        /// <param name="result">The result vector, <c>x</c></param>
        public void Solve(Matrix matrix, Vector input, Vector result)
        {
            // If we were stopped before, we are no longer
            // We're doing this at the start of the method to ensure
            // that we can use these fields immediately.
            _hasBeenStopped = false;

            // Error checks
            if (matrix == null)
            {
                throw new ArgumentNullException("matrix");
            }

            if (matrix.RowCount != matrix.ColumnCount)
            {
                throw new ArgumentException(Resources.ArgumentMatrixSquare, "matrix");
            }

            if (input == null)
            {
                throw new ArgumentNullException("input");
            }

            if (result == null)
            {
                throw new ArgumentNullException("result");
            }

            if (result.Count != input.Count)
            {
                throw new ArgumentException(Resources.ArgumentVectorsSameLength);
            }

            if (input.Count != matrix.RowCount)
            {
                throw Matrix.DimensionsDontMatch <ArgumentException>(input, matrix);
            }

            // Initialize the solver fields
            // Set the convergence monitor
            if (_iterator == null)
            {
                _iterator = Iterator.CreateDefault();
            }

            if (_preconditioner == null)
            {
                _preconditioner = new UnitPreconditioner();
            }

            _preconditioner.Initialize(matrix);

            // x_0 is initial guess
            // Take x_0 = 0
            Vector xtemp = new DenseVector(input.Count);

            // r_0 = b - Ax_0
            // This is basically a SAXPY so it could be made a lot faster
            Vector residuals = new DenseVector(matrix.RowCount);

            CalculateTrueResidual(matrix, residuals, xtemp, input);

            // Define the temporary scalars
            Complex32 beta = 0;

            // Define the temporary vectors
            // rDash_0 = r_0
            Vector rdash = new DenseVector(residuals);

            // t_-1 = 0
            Vector t  = new DenseVector(residuals.Count);
            Vector t0 = new DenseVector(residuals.Count);

            // w_-1 = 0
            Vector w = new DenseVector(residuals.Count);

            // Define the remaining temporary vectors
            Vector c = new DenseVector(residuals.Count);
            Vector p = new DenseVector(residuals.Count);
            Vector s = new DenseVector(residuals.Count);
            Vector u = new DenseVector(residuals.Count);
            Vector y = new DenseVector(residuals.Count);
            Vector z = new DenseVector(residuals.Count);

            Vector temp  = new DenseVector(residuals.Count);
            Vector temp2 = new DenseVector(residuals.Count);
            Vector temp3 = new DenseVector(residuals.Count);

            // for (k = 0, 1, .... )
            var iterationNumber = 0;

            while (ShouldContinue(iterationNumber, xtemp, input, residuals))
            {
                // p_k = r_k + beta_(k-1) * (p_(k-1) - u_(k-1))
                p.Subtract(u, temp);

                temp.Multiply(beta, temp2);
                residuals.Add(temp2, p);

                // Solve M b_k = p_k
                _preconditioner.Approximate(p, temp);

                // s_k = A b_k
                matrix.Multiply(temp, s);

                // alpha_k = (r*_0 * r_k) / (r*_0 * s_k)
                var alpha = rdash.DotProduct(residuals) / rdash.DotProduct(s);

                // y_k = t_(k-1) - r_k - alpha_k * w_(k-1) + alpha_k s_k
                s.Subtract(w, temp);
                t.Subtract(residuals, y);

                temp.Multiply(alpha, temp2);
                y.Add(temp2, temp3);
                temp3.CopyTo(y);

                // Store the old value of t in t0
                t.CopyTo(t0);

                // t_k = r_k - alpha_k s_k
                s.Multiply(-alpha, temp2);
                residuals.Add(temp2, t);

                // Solve M d_k = t_k
                _preconditioner.Approximate(t, temp);

                // c_k = A d_k
                matrix.Multiply(temp, c);
                var cdot = c.DotProduct(c);

                // cDot can only be zero if c is a zero vector
                // We'll set cDot to 1 if it is zero to prevent NaN's
                // Note that the calculation should continue fine because
                // c.DotProduct(t) will be zero and so will c.DotProduct(y)
                if (cdot.Real.AlmostEqual(0, 1) && cdot.Imaginary.AlmostEqual(0, 1))
                {
                    cdot = 1.0f;
                }

                // Even if we don't want to do any BiCGStab steps we'll still have
                // to do at least one at the start to initialize the
                // system, but we'll only have to take special measures
                // if we don't do any so ...
                var       ctdot = c.DotProduct(t);
                Complex32 eta;
                Complex32 sigma;
                if (((_numberOfBiCgStabSteps == 0) && (iterationNumber == 0)) || ShouldRunBiCgStabSteps(iterationNumber))
                {
                    // sigma_k = (c_k * t_k) / (c_k * c_k)
                    sigma = ctdot / cdot;

                    // eta_k = 0
                    eta = 0;
                }
                else
                {
                    var ydot = y.DotProduct(y);

                    // yDot can only be zero if y is a zero vector
                    // We'll set yDot to 1 if it is zero to prevent NaN's
                    // Note that the calculation should continue fine because
                    // y.DotProduct(t) will be zero and so will c.DotProduct(y)
                    if (ydot.Real.AlmostEqual(0, 1) && ydot.Imaginary.AlmostEqual(0, 1))
                    {
                        ydot = 1.0f;
                    }

                    var ytdot = y.DotProduct(t);
                    var cydot = c.DotProduct(y);

                    var denom = (cdot * ydot) - (cydot * cydot);

                    // sigma_k = ((y_k * y_k)(c_k * t_k) - (y_k * t_k)(c_k * y_k)) / ((c_k * c_k)(y_k * y_k) - (y_k * c_k)(c_k * y_k))
                    sigma = ((ydot * ctdot) - (ytdot * cydot)) / denom;

                    // eta_k = ((c_k * c_k)(y_k * t_k) - (y_k * c_k)(c_k * t_k)) / ((c_k * c_k)(y_k * y_k) - (y_k * c_k)(c_k * y_k))
                    eta = ((cdot * ytdot) - (cydot * ctdot)) / denom;
                }

                // u_k = sigma_k s_k + eta_k (t_(k-1) - r_k + beta_(k-1) u_(k-1))
                u.Multiply(beta, temp2);
                t0.Add(temp2, temp);

                temp.Subtract(residuals, temp3);
                temp3.CopyTo(temp);
                temp.Multiply(eta, temp);

                s.Multiply(sigma, temp2);
                temp.Add(temp2, u);

                // z_k = sigma_k r_k +_ eta_k z_(k-1) - alpha_k u_k
                z.Multiply(eta, z);
                u.Multiply(-alpha, temp2);
                z.Add(temp2, temp3);
                temp3.CopyTo(z);

                residuals.Multiply(sigma, temp2);
                z.Add(temp2, temp3);
                temp3.CopyTo(z);

                // x_(k+1) = x_k + alpha_k p_k + z_k
                p.Multiply(alpha, temp2);
                xtemp.Add(temp2, temp3);
                temp3.CopyTo(xtemp);

                xtemp.Add(z, temp3);
                temp3.CopyTo(xtemp);

                // r_(k+1) = t_k - eta_k y_k - sigma_k c_k
                // Copy the old residuals to a temp vector because we'll
                // need those in the next step
                residuals.CopyTo(t0);

                y.Multiply(-eta, temp2);
                t.Add(temp2, residuals);

                c.Multiply(-sigma, temp2);
                residuals.Add(temp2, temp3);
                temp3.CopyTo(residuals);

                // beta_k = alpha_k / sigma_k * (r*_0 * r_(k+1)) / (r*_0 * r_k)
                // But first we check if there is a possible NaN. If so just reset beta to zero.
                beta = (!sigma.Real.AlmostEqual(0, 1) || !sigma.Imaginary.AlmostEqual(0, 1)) ? alpha / sigma * rdash.DotProduct(residuals) / rdash.DotProduct(t0) : 0;

                // w_k = c_k + beta_k s_k
                s.Multiply(beta, temp2);
                c.Add(temp2, w);

                // Get the real value
                _preconditioner.Approximate(xtemp, result);

                // Now check for convergence
                if (!ShouldContinue(iterationNumber, result, input, residuals))
                {
                    // Recalculate the residuals and go round again. This is done to ensure that
                    // we have the proper residuals.
                    CalculateTrueResidual(matrix, residuals, result, input);
                }

                // Next iteration.
                iterationNumber++;
            }
        }