Ejemplo n.º 1
0
        public void CanCreateSparseVectorFromArray()
        {
            var data = new Complex32[Data.Length];
            Array.Copy(Data, data, Data.Length);
            var vector = new SparseVector(data);

            for (var i = 0; i < data.Length; i++)
            {
                Assert.AreEqual(data[i], vector[i]);
            }
        }
Ejemplo n.º 2
0
        public void CanWriteMatrices()
        {
            Matrix mat1 = new DenseMatrix(5, 3);
            for (var i = 0; i < mat1.ColumnCount; i++)
            {
                mat1[i, i] = new Complex32(i + .1f, i + .1f);
            }

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

            Matrix mat3 = new SparseMatrix(5, 4);
            for (var i = 0; i < mat3.ColumnCount; i++)
            {
                mat3[i, i] = new Complex32(i + .1f, i + .1f);
            }

            Matrix mat4 = new SparseMatrix(3, 5);
            for (var i = 0; i < mat4.RowCount; i++)
            {
                mat4[i, i] = new Complex32(i + .1f, i + .1f);
            }

            var write = new[] { mat1, mat2, mat3, mat4 };

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

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

            var reader = new MatlabMatrixReader("test.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));
            }
        }
Ejemplo n.º 3
0
        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 void CanMultiplyWithComplex([Values(0, 1, 2.2f)] 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]);
                }
            }
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Creates a positive definite <c>DenseMatrix</c> with random values.
        /// </summary>
        /// <param name="order">The order of the matrix.</param>
        /// <returns>A positive definite <c>DenseMatrix</c> with the given order and random values.</returns>
        public static Matrix <Complex32> GenerateRandomPositiveDefiniteHermitianDenseMatrix(int order)
        {
            // Fill a matrix with standard random numbers.
            var normal = new Normal
            {
                RandomSource = new MersenneTwister(1)
            };
            var matrixA = new DenseMatrix(order);

            for (var i = 0; i < order; i++)
            {
                for (var j = 0; j < order; j++)
                {
                    matrixA[i, j] = new Complex32((float)normal.Sample(), (float)normal.Sample());
                }
            }

            // Generate a Hermitian matrix which is positive definite.
            return(matrixA.ConjugateTranspose() * matrixA);
        }
Ejemplo n.º 6
0
        public void CheckSparseMechanismByZeroMultiply()
        {
            var vector = new SparseVector(10000);

            // Add non-zero elements
            vector[200] = new Complex32(1.5f, 1);
            vector[500] = new Complex32(3.5f, 1);
            vector[800] = new Complex32(5.5f, 1);
            vector[0]   = new Complex32(7.5f, 1);

            // Multiply by 0
            vector *= 0;

            var storage = (SparseVectorStorage <Complex32>)vector.Storage;

            Assert.AreEqual(Complex32.Zero, vector[200]);
            Assert.AreEqual(Complex32.Zero, vector[500]);
            Assert.AreEqual(Complex32.Zero, vector[800]);
            Assert.AreEqual(Complex32.Zero, vector[0]);
            Assert.AreEqual(0, storage.ValueCount);
        }
Ejemplo n.º 7
0
        public void CheckSparseMechanismBySettingValues()
        {
            var vector  = new SparseVector(10000);
            var storage = (SparseVectorStorage <Complex32>)vector.Storage;

            // Add non-zero elements
            vector[200] = new Complex32(1.5f, 1);
            Assert.AreEqual(new Complex32(1.5f, 1), vector[200]);
            Assert.AreEqual(1, storage.ValueCount);

            vector[500] = new Complex32(3.5f, 1);
            Assert.AreEqual(new Complex32(3.5f, 1), vector[500]);
            Assert.AreEqual(2, storage.ValueCount);

            vector[800] = new Complex32(5.5f, 1);
            Assert.AreEqual(new Complex32(5.5f, 1), vector[800]);
            Assert.AreEqual(3, storage.ValueCount);

            vector[0] = new Complex32(7.5f, 1);
            Assert.AreEqual(new Complex32(7.5f, 1), vector[0]);
            Assert.AreEqual(4, storage.ValueCount);

            // Remove non-zero elements
            vector[200] = Complex32.Zero;
            Assert.AreEqual(Complex32.Zero, vector[200]);
            Assert.AreEqual(3, storage.ValueCount);

            vector[500] = Complex32.Zero;
            Assert.AreEqual(Complex32.Zero, vector[500]);
            Assert.AreEqual(2, storage.ValueCount);

            vector[800] = Complex32.Zero;
            Assert.AreEqual(Complex32.Zero, vector[800]);
            Assert.AreEqual(1, storage.ValueCount);

            vector[0] = Complex32.Zero;
            Assert.AreEqual(Complex32.Zero, vector[0]);
            Assert.AreEqual(0, storage.ValueCount);
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Reduces a complex hermitian matrix to a real symmetric tridiagonal matrix using unitary similarity transformations.
        /// </summary>
        /// <param name="matrixA">Source matrix to reduce</param>
        /// <param name="d">Output: Arrays for internal storage of real parts of eigenvalues</param>
        /// <param name="e">Output: Arrays for internal storage of imaginary parts of eigenvalues</param>
        /// <param name="tau">Output: Arrays that contains further information about the transformations.</param>
        /// <param name="order">Order of initial matrix</param>
        /// <remarks>This is derived from the Algol procedures HTRIDI by
        /// Smith, Boyle, Dongarra, Garbow, Ikebe, Klema, Moler, and Wilkinson, Handbook for
        /// Auto. Comp., Vol.ii-Linear Algebra, and the corresponding
        /// Fortran subroutine in EISPACK.</remarks>
        internal static void SymmetricTridiagonalize(Numerics.Complex32[] matrixA, float[] d, float[] e, Numerics.Complex32[] tau, int order)
        {
            float hh;

            tau[order - 1] = Numerics.Complex32.One;

            for (var i = 0; i < order; i++)
            {
                d[i] = matrixA[i * order + i].Real;
            }

            // Householder reduction to tridiagonal form.
            for (var i = order - 1; i > 0; i--)
            {
                // Scale to avoid under/overflow.
                var scale = 0.0f;
                var h     = 0.0f;

                for (var k = 0; k < i; k++)
                {
                    scale = scale + Math.Abs(matrixA[k * order + i].Real) + Math.Abs(matrixA[k * order + i].Imaginary);
                }

                if (scale == 0.0f)
                {
                    tau[i - 1] = Numerics.Complex32.One;
                    e[i]       = 0.0f;
                }
                else
                {
                    for (var k = 0; k < i; k++)
                    {
                        matrixA[k * order + i] /= scale;
                        h += matrixA[k * order + i].MagnitudeSquared;
                    }

                    Numerics.Complex32 g = (float)Math.Sqrt(h);
                    e[i] = scale * g.Real;

                    Numerics.Complex32 temp;
                    var im1Oi = (i - 1) * order + i;
                    var f     = matrixA[im1Oi];
                    if (f.Magnitude != 0.0f)
                    {
                        temp            = -(matrixA[im1Oi].Conjugate() * tau[i].Conjugate()) / f.Magnitude;
                        h              += f.Magnitude * g.Real;
                        g               = 1.0f + (g / f.Magnitude);
                        matrixA[im1Oi] *= g;
                    }
                    else
                    {
                        temp           = -tau[i].Conjugate();
                        matrixA[im1Oi] = g;
                    }

                    if ((f.Magnitude == 0.0f) || (i != 1))
                    {
                        f = Numerics.Complex32.Zero;
                        for (var j = 0; j < i; j++)
                        {
                            var tmp = Numerics.Complex32.Zero;
                            var jO  = j * order;
                            // Form element of A*U.
                            for (var k = 0; k <= j; k++)
                            {
                                tmp += matrixA[k * order + j] * matrixA[k * order + i].Conjugate();
                            }

                            for (var k = j + 1; k <= i - 1; k++)
                            {
                                tmp += matrixA[jO + k].Conjugate() * matrixA[k * order + i].Conjugate();
                            }

                            // Form element of P
                            tau[j] = tmp / h;
                            f     += (tmp / h) * matrixA[jO + i];
                        }

                        hh = f.Real / (h + h);

                        // Form the reduced A.
                        for (var j = 0; j < i; j++)
                        {
                            f      = matrixA[j * order + i].Conjugate();
                            g      = tau[j] - (hh * f);
                            tau[j] = g.Conjugate();

                            for (var k = 0; k <= j; k++)
                            {
                                matrixA[k * order + j] -= (f * tau[k]) + (g * matrixA[k * order + i]);
                            }
                        }
                    }

                    for (var k = 0; k < i; k++)
                    {
                        matrixA[k * order + i] *= scale;
                    }

                    tau[i - 1] = temp.Conjugate();
                }

                hh   = d[i];
                d[i] = matrixA[i * order + i].Real;
                matrixA[i * order + i] = new Numerics.Complex32(hh, scale * (float)Math.Sqrt(h));
            }

            hh         = d[0];
            d[0]       = matrixA[0].Real;
            matrixA[0] = hh;
            e[0]       = 0.0f;
        }
 /// <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>
 protected internal override void At(int index, Complex32 value)
 {
     this[index] = value;
 }
Ejemplo n.º 10
0
        /// <summary>
        /// Solves a system of linear equations, <b>Ax = b</b>, with A EVD 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 <Numerics.Complex32> input, Vector <Numerics.Complex32> result)
        {
            if (input == null)
            {
                throw new ArgumentNullException("input");
            }

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

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

            // Check that x is a column vector with n entries
            if (VectorEv.Count != result.Count)
            {
                throw new ArgumentException(Resources.ArgumentMatrixDimensions);
            }

            if (IsSymmetric)
            {
                // Symmetric case -> x = V * inv(λ) * VH * b;
                var order = VectorEv.Count;
                var tmp   = new Numerics.Complex32[order];
                Numerics.Complex32 value;

                for (var j = 0; j < order; j++)
                {
                    value = 0;
                    if (j < order)
                    {
                        for (var i = 0; i < order; i++)
                        {
                            value += ((DenseMatrix)MatrixEv).Values[(j * order) + i].Conjugate() * input[i];
                        }

                        value /= (float)VectorEv[j].Real;
                    }

                    tmp[j] = value;
                }

                for (var j = 0; j < order; j++)
                {
                    value = 0;
                    for (var i = 0; i < order; i++)
                    {
                        value += ((DenseMatrix)MatrixEv).Values[(i * order) + j] * tmp[i];
                    }

                    result[j] = value;
                }
            }
            else
            {
                throw new ArgumentException(Resources.ArgumentMatrixSymmetric);
            }
        }
Ejemplo n.º 11
0
 public void CanSum()
 {
     Complex32[] testData = { new Complex32(-20, -1), new Complex32(-10, -1), new Complex32(10, 1), new Complex32(20, 1), new Complex32(30, 1) };
     var vector = CreateVector(testData);
     var actual = vector.Sum();
     var expected = new Complex32(30, 1);
     Assert.AreEqual(expected, actual);
 }
Ejemplo n.º 12
0
        public void CanMultiplySparseVectorByComplexUsingOperators()
        {
            var vector = new SparseVector(Data);
            vector = vector * new Complex32(2.0f, 1);

            for (var i = 0; i < Data.Length; i++)
            {
                Assert.AreEqual(Data[i] * new Complex32(2.0f, 1), vector[i]);
            }

            vector = vector * 1.0f;
            for (var i = 0; i < Data.Length; i++)
            {
                Assert.AreEqual(Data[i] * new Complex32(2.0f, 1), vector[i]);
            }

            vector = new SparseVector(Data);
            vector = new Complex32(2.0f, 1) * vector;

            for (var i = 0; i < Data.Length; i++)
            {
                Assert.AreEqual(Data[i] * new Complex32(2.0f, 1), vector[i]);
            }

            vector = 1.0f * vector;
            for (var i = 0; i < Data.Length; i++)
            {
                Assert.AreEqual(Data[i] * new Complex32(2.0f, 1), vector[i]);
            }
        }
Ejemplo n.º 13
0
        public void CheckSparseMechanismByZeroMultiply()
        {
            var vector = new SparseVector(10000);

            // Add non-zero elements
            vector[200] = new Complex32(1.5f, 1);
            vector[500] = new Complex32(3.5f, 1);
            vector[800] = new Complex32(5.5f, 1);
            vector[0] = new Complex32(7.5f, 1);

            // Multiply by 0
            vector *= 0;
            Assert.AreEqual(Complex32.Zero, vector[200]);
            Assert.AreEqual(Complex32.Zero, vector[500]);
            Assert.AreEqual(Complex32.Zero, vector[800]);
            Assert.AreEqual(Complex32.Zero, vector[0]);
            Assert.AreEqual(0, vector.NonZerosCount);
        }
 /// <summary>
 /// Creates a matrix from a 2D array.
 /// </summary>
 /// <param name="data">The 2D array to create this matrix from.</param>
 /// <returns>A matrix with the given values.</returns>
 protected override Matrix CreateMatrix(Complex32[,] data)
 {
     return SparseMatrix.OfArray(data);
 }
Ejemplo n.º 15
0
 /// <summary>
 /// Creates a matrix from a 2D array.
 /// </summary>
 /// <param name="data">The 2D array to create this matrix from.</param>
 /// <returns>A matrix with the given values.</returns>
 protected override Matrix CreateMatrix(Complex32[,] data)
 {
     return new SparseMatrix(data);
 }
Ejemplo n.º 16
0
        public void CanSetDiagonalVector(string name, float[] real)
        {
            var diagonal = new Complex32[real.Length];
            for (var i = 0; i < real.Length; i++)
            {
                diagonal[i] = new Complex32(real[i], 1);
            }

            var matrix = TestMatrices[name];
            var vector = CreateVector(diagonal);
            matrix.SetDiagonal(vector);

            var min = Math.Min(matrix.ColumnCount, matrix.RowCount);
            Assert.AreEqual(diagonal.Length, min);

            for (var i = 0; i < vector.Count; i++)
            {
                Assert.AreEqual(vector[i], matrix[i, i]);
            }
        }
Ejemplo n.º 17
0
        public virtual void CanSetRowWithVector(string name, float[] real)
        {
            var row = new Complex32[real.Length];
            for (var i = 0; i < real.Length; i++)
            {
                row[i] = new Complex32(real[i], 1);
            }

            var matrix = TestMatrices[name];
            var rowVector = CreateVector(row);
            for (var i = 0; i < matrix.RowCount; i++)
            {
                matrix.SetRow(i, row);
                for (var j = 0; j < matrix.ColumnCount; j++)
                {
                    Assert.AreEqual(matrix[i, j], rowVector[j]);
                }
            }
        }
Ejemplo n.º 18
0
        /// <summary>
        /// Nonsymmetric reduction to Hessenberg form.
        /// </summary>
        /// <param name="dataEv">Data array of matrix V (eigenvectors)</param>
        /// <param name="matrixH">Array for internal storage of nonsymmetric Hessenberg form.</param>
        /// <param name="order">Order of initial matrix</param>
        /// <remarks>This is derived from the Algol procedures orthes and ortran,
        /// by Martin and Wilkinson, Handbook for Auto. Comp.,
        /// Vol.ii-Linear Algebra, and the corresponding
        /// Fortran subroutines in EISPACK.</remarks>
        internal static void NonsymmetricReduceToHessenberg(Numerics.Complex32[] dataEv, Numerics.Complex32[] matrixH, int order)
        {
            var ort = new Numerics.Complex32[order];

            for (var m = 1; m < order - 1; m++)
            {
                // Scale column.
                var scale = 0.0f;
                var mm1O  = (m - 1) * order;
                for (var i = m; i < order; i++)
                {
                    scale += Math.Abs(matrixH[mm1O + i].Real) + Math.Abs(matrixH[mm1O + i].Imaginary);
                }

                if (scale != 0.0f)
                {
                    // Compute Householder transformation.
                    var h = 0.0f;
                    for (var i = order - 1; i >= m; i--)
                    {
                        ort[i] = matrixH[mm1O + i] / scale;
                        h     += ort[i].MagnitudeSquared;
                    }

                    var g = (float)Math.Sqrt(h);
                    if (ort[m].Magnitude != 0)
                    {
                        h      = h + (ort[m].Magnitude * g);
                        g     /= ort[m].Magnitude;
                        ort[m] = (1.0f + g) * ort[m];
                    }
                    else
                    {
                        ort[m]            = g;
                        matrixH[mm1O + m] = scale;
                    }

                    // Apply Householder similarity transformation
                    // H = (I-u*u'/h)*H*(I-u*u')/h)
                    for (var j = m; j < order; j++)
                    {
                        var f  = Numerics.Complex32.Zero;
                        var jO = j * order;
                        for (var i = order - 1; i >= m; i--)
                        {
                            f += ort[i].Conjugate() * matrixH[jO + i];
                        }

                        f = f / h;
                        for (var i = m; i < order; i++)
                        {
                            matrixH[jO + i] -= f * ort[i];
                        }
                    }

                    for (var i = 0; i < order; i++)
                    {
                        var f = Numerics.Complex32.Zero;
                        for (var j = order - 1; j >= m; j--)
                        {
                            f += ort[j] * matrixH[j * order + i];
                        }

                        f = f / h;
                        for (var j = m; j < order; j++)
                        {
                            matrixH[j * order + i] -= f * ort[j].Conjugate();
                        }
                    }

                    ort[m]             = scale * ort[m];
                    matrixH[mm1O + m] *= -g;
                }
            }

            // Accumulate transformations (Algol's ortran).
            for (var i = 0; i < order; i++)
            {
                for (var j = 0; j < order; j++)
                {
                    dataEv[(j * order) + i] = i == j ? Numerics.Complex32.One : Numerics.Complex32.Zero;
                }
            }

            for (var m = order - 2; m >= 1; m--)
            {
                var mm1O  = (m - 1) * order;
                var mm1Om = mm1O + m;
                if (matrixH[mm1Om] != Numerics.Complex32.Zero && ort[m] != Numerics.Complex32.Zero)
                {
                    var norm = (matrixH[mm1Om].Real * ort[m].Real) + (matrixH[mm1Om].Imaginary * ort[m].Imaginary);

                    for (var i = m + 1; i < order; i++)
                    {
                        ort[i] = matrixH[mm1O + i];
                    }

                    for (var j = m; j < order; j++)
                    {
                        var g = Numerics.Complex32.Zero;
                        for (var i = m; i < order; i++)
                        {
                            g += ort[i].Conjugate() * dataEv[(j * order) + i];
                        }

                        // Double division avoids possible underflow
                        g /= norm;
                        for (var i = m; i < order; i++)
                        {
                            dataEv[(j * order) + i] += g * ort[i];
                        }
                    }
                }
            }

            // Create real subdiagonal elements.
            for (var i = 1; i < order; i++)
            {
                var im1   = i - 1;
                var im1O  = im1 * order;
                var im1Oi = im1O + i;
                var iO    = i * order;
                if (matrixH[im1Oi].Imaginary != 0.0f)
                {
                    var y = matrixH[im1Oi] / matrixH[im1Oi].Magnitude;
                    matrixH[im1Oi] = matrixH[im1Oi].Magnitude;
                    for (var j = i; j < order; j++)
                    {
                        matrixH[j * order + i] *= y.Conjugate();
                    }

                    for (var j = 0; j <= Math.Min(i + 1, order - 1); j++)
                    {
                        matrixH[iO + j] *= y;
                    }

                    for (var j = 0; j < order; j++)
                    {
                        dataEv[(i * order) + j] *= y;
                    }
                }
            }
        }
Ejemplo n.º 19
0
        /// <summary>
        /// Nonsymmetric reduction from Hessenberg to real Schur form.
        /// </summary>
        /// <param name="vectorV">Data array of the eigenvectors</param>
        /// <param name="dataEv">Data array of matrix V (eigenvectors)</param>
        /// <param name="matrixH">Array for internal storage of nonsymmetric Hessenberg form.</param>
        /// <param name="order">Order of initial matrix</param>
        /// <remarks>This is derived from the Algol procedure hqr2,
        /// by Martin and Wilkinson, Handbook for Auto. Comp.,
        /// Vol.ii-Linear Algebra, and the corresponding
        /// Fortran subroutine in EISPACK.</remarks>
        internal static void NonsymmetricReduceHessenberToRealSchur(Numerics.Complex32[] vectorV, Numerics.Complex32[] dataEv, Numerics.Complex32[] matrixH, int order)
        {
            // Initialize
            var n   = order - 1;
            var eps = (float)Precision.SingleMachinePrecision;

            float norm;

            Numerics.Complex32 x, y, z, exshift = Numerics.Complex32.Zero;

            // Outer loop over eigenvalue index
            var iter = 0;

            while (n >= 0)
            {
                // Look for single small sub-diagonal element
                var l = n;
                while (l > 0)
                {
                    var lm1  = l - 1;
                    var lm1O = lm1 * order;
                    var lO   = l * order;
                    var tst1 = Math.Abs(matrixH[lm1O + lm1].Real) + Math.Abs(matrixH[lm1O + lm1].Imaginary) + Math.Abs(matrixH[lO + l].Real) + Math.Abs(matrixH[lO + l].Imaginary);
                    if (Math.Abs(matrixH[lm1O + l].Real) < eps * tst1)
                    {
                        break;
                    }

                    l--;
                }

                var nm1  = n - 1;
                var nm1O = nm1 * order;
                var nO   = n * order;
                var nOn  = nO + n;
                // Check for convergence
                // One root found
                if (l == n)
                {
                    matrixH[nOn] += exshift;
                    vectorV[n]    = matrixH[nOn];
                    n--;
                    iter = 0;
                }
                else
                {
                    // Form shift
                    Numerics.Complex32 s;
                    if (iter != 10 && iter != 20)
                    {
                        s = matrixH[nOn];
                        x = matrixH[nO + nm1] * matrixH[nm1O + n].Real;

                        if (x.Real != 0.0f || x.Imaginary != 0.0f)
                        {
                            y = (matrixH[nm1O + nm1] - s) / 2.0f;
                            z = ((y * y) + x).SquareRoot();
                            if ((y.Real * z.Real) + (y.Imaginary * z.Imaginary) < 0.0)
                            {
                                z *= -1.0f;
                            }

                            x /= y + z;
                            s  = s - x;
                        }
                    }
                    else
                    {
                        // Form exceptional shift
                        s = Math.Abs(matrixH[nm1O + n].Real) + Math.Abs(matrixH[(n - 2) * order + nm1].Real);
                    }

                    for (var i = 0; i <= n; i++)
                    {
                        matrixH[i * order + i] -= s;
                    }

                    exshift += s;
                    iter++;

                    // Reduce to triangle (rows)
                    for (var i = l + 1; i <= n; i++)
                    {
                        var im1     = i - 1;
                        var im1O    = im1 * order;
                        var im1Oim1 = im1O + im1;
                        s                 = matrixH[im1O + i].Real;
                        norm              = SpecialFunctions.Hypotenuse(matrixH[im1Oim1].Magnitude, s.Real);
                        x                 = matrixH[im1Oim1] / norm;
                        vectorV[i - 1]    = x;
                        matrixH[im1Oim1]  = norm;
                        matrixH[im1O + i] = new Numerics.Complex32(0.0f, s.Real / norm);

                        for (var j = i; j < order; j++)
                        {
                            var jO = j * order;
                            y = matrixH[jO + im1];
                            z = matrixH[jO + i];
                            matrixH[jO + im1] = (x.Conjugate() * y) + (matrixH[im1O + i].Imaginary * z);
                            matrixH[jO + i]   = (x * z) - (matrixH[im1O + i].Imaginary * y);
                        }
                    }

                    s = matrixH[nOn];
                    if (s.Imaginary != 0.0f)
                    {
                        s           /= matrixH[nOn].Magnitude;
                        matrixH[nOn] = matrixH[nOn].Magnitude;

                        for (var j = n + 1; j < order; j++)
                        {
                            matrixH[j * order + n] *= s.Conjugate();
                        }
                    }

                    // Inverse operation (columns).
                    for (var j = l + 1; j <= n; j++)
                    {
                        x = vectorV[j - 1];
                        var jO    = j * order;
                        var jm1   = j - 1;
                        var jm1O  = jm1 * order;
                        var jm1Oj = jm1O + j;
                        for (var i = 0; i <= j; i++)
                        {
                            var jm1Oi = jm1O + i;
                            z = matrixH[jO + i];
                            if (i != j)
                            {
                                y = matrixH[jm1Oi];
                                matrixH[jm1Oi] = (x * y) + (matrixH[jm1O + j].Imaginary * z);
                            }
                            else
                            {
                                y = matrixH[jm1Oi].Real;
                                matrixH[jm1Oi] = new Numerics.Complex32((x.Real * y.Real) - (x.Imaginary * y.Imaginary) + (matrixH[jm1O + j].Imaginary * z.Real), matrixH[jm1Oi].Imaginary);
                            }

                            matrixH[jO + i] = (x.Conjugate() * z) - (matrixH[jm1O + j].Imaginary * y);
                        }

                        for (var i = 0; i < order; i++)
                        {
                            y = dataEv[((j - 1) * order) + i];
                            z = dataEv[(j * order) + i];
                            dataEv[jm1O + i] = (x * y) + (matrixH[jm1Oj].Imaginary * z);
                            dataEv[jO + i]   = (x.Conjugate() * z) - (matrixH[jm1Oj].Imaginary * y);
                        }
                    }

                    if (s.Imaginary != 0.0f)
                    {
                        for (var i = 0; i <= n; i++)
                        {
                            matrixH[nO + i] *= s;
                        }

                        for (var i = 0; i < order; i++)
                        {
                            dataEv[nO + i] *= s;
                        }
                    }
                }
            }

            // All roots found.
            // Backsubstitute to find vectors of upper triangular form
            norm = 0.0f;
            for (var i = 0; i < order; i++)
            {
                for (var j = i; j < order; j++)
                {
                    norm = Math.Max(norm, Math.Abs(matrixH[j * order + i].Real) + Math.Abs(matrixH[j * order + i].Imaginary));
                }
            }

            if (order == 1)
            {
                return;
            }

            if (norm == 0.0)
            {
                return;
            }

            for (n = order - 1; n > 0; n--)
            {
                var nO  = n * order;
                var nOn = nO + n;
                x            = vectorV[n];
                matrixH[nOn] = 1.0f;

                for (var i = n - 1; i >= 0; i--)
                {
                    z = 0.0f;
                    for (var j = i + 1; j <= n; j++)
                    {
                        z += matrixH[j * order + i] * matrixH[nO + j];
                    }

                    y = x - vectorV[i];
                    if (y.Real == 0.0f && y.Imaginary == 0.0f)
                    {
                        y = eps * norm;
                    }

                    matrixH[nO + i] = z / y;

                    // Overflow control
                    var tr = Math.Abs(matrixH[nO + i].Real) + Math.Abs(matrixH[nO + i].Imaginary);
                    if ((eps * tr) * tr > 1)
                    {
                        for (var j = i; j <= n; j++)
                        {
                            matrixH[nO + j] = matrixH[nO + j] / tr;
                        }
                    }
                }
            }

            // Back transformation to get eigenvectors of original matrix
            for (var j = order - 1; j > 0; j--)
            {
                var jO = j * order;
                for (var i = 0; i < order; i++)
                {
                    z = Numerics.Complex32.Zero;
                    for (var k = 0; k <= j; k++)
                    {
                        z += dataEv[(k * order) + i] * matrixH[jO + k];
                    }

                    dataEv[jO + i] = z;
                }
            }
        }
Ejemplo n.º 20
0
 /// <summary>
 /// Sets the value of the given element.
 /// </summary>
 /// <param name="row">The row of the element.</param>
 /// <param name="column">The column of the element.</param>
 /// <param name="value">The value to set the element to. </param>
 public override void At(int row, int column, Complex32 value)
 {
     _data[row, column] = value;
 }
Ejemplo n.º 21
0
 public void MatrixFrom1DArrayIsCopy()
 {
     // Sparse Matrix copies values from Complex32[], but no remember reference.
     var data = new[] { new Complex32(1.0f, 1), new Complex32(1.0f, 1), new Complex32(1.0f, 1), new Complex32(1.0f, 1), new Complex32(1.0f, 1), new Complex32(1.0f, 1), new Complex32(2.0f, 1), new Complex32(2.0f, 1), new Complex32(2.0f, 1) };
     var matrix = new SparseMatrix(3, 3, data);
     matrix[0, 0] = new Complex32(10.0f, 1);
     Assert.AreNotEqual(new Complex32(10.0f, 1), data[0]);
 }
Ejemplo n.º 22
0
        /// <summary>
        /// Reduces a complex hermitian matrix to a real symmetric tridiagonal matrix using unitary similarity transformations.
        /// </summary>
        /// <param name="matrixA">Source matrix to reduce</param>
        /// <param name="d">Output: Arrays for internal storage of real parts of eigenvalues</param>
        /// <param name="e">Output: Arrays for internal storage of imaginary parts of eigenvalues</param>
        /// <param name="tau">Output: Arrays that contains further information about the transformations.</param>
        /// <param name="order">Order of initial matrix</param>
        /// <remarks>This is derived from the Algol procedures HTRIDI by 
        /// Smith, Boyle, Dongarra, Garbow, Ikebe, Klema, Moler, and Wilkinson, Handbook for 
        /// Auto. Comp., Vol.ii-Linear Algebra, and the corresponding 
        /// Fortran subroutine in EISPACK.</remarks>
        internal static void SymmetricTridiagonalize(Numerics.Complex32[] matrixA, float[] d, float[] e, Numerics.Complex32[] tau, int order)
        {
            float hh;
            tau[order - 1] = Numerics.Complex32.One;

            for (var i = 0; i < order; i++)
            {
                d[i] = matrixA[i*order + i].Real;
            }

            // Householder reduction to tridiagonal form.
            for (var i = order - 1; i > 0; i--)
            {
                // Scale to avoid under/overflow.
                var scale = 0.0f;
                var h = 0.0f;

                for (var k = 0; k < i; k++)
                {
                    scale = scale + Math.Abs(matrixA[k*order + i].Real) + Math.Abs(matrixA[k*order + i].Imaginary);
                }

                if (scale == 0.0f)
                {
                    tau[i - 1] = Numerics.Complex32.One;
                    e[i] = 0.0f;
                }
                else
                {
                    for (var k = 0; k < i; k++)
                    {
                        matrixA[k*order + i] /= scale;
                        h += matrixA[k*order + i].MagnitudeSquared;
                    }

                    Numerics.Complex32 g = (float) Math.Sqrt(h);
                    e[i] = scale*g.Real;

                    Numerics.Complex32 temp;
                    var im1Oi = (i - 1)*order + i;
                    var f = matrixA[im1Oi];
                    if (f.Magnitude != 0.0f)
                    {
                        temp = -(matrixA[im1Oi].Conjugate()*tau[i].Conjugate())/f.Magnitude;
                        h += f.Magnitude*g.Real;
                        g = 1.0f + (g/f.Magnitude);
                        matrixA[im1Oi] *= g;
                    }
                    else
                    {
                        temp = -tau[i].Conjugate();
                        matrixA[im1Oi] = g;
                    }

                    if ((f.Magnitude == 0.0f) || (i != 1))
                    {
                        f = Numerics.Complex32.Zero;
                        for (var j = 0; j < i; j++)
                        {
                            var tmp = Numerics.Complex32.Zero;
                            var jO = j*order;
                            // Form element of A*U.
                            for (var k = 0; k <= j; k++)
                            {
                                tmp += matrixA[k*order + j]*matrixA[k*order + i].Conjugate();
                            }

                            for (var k = j + 1; k <= i - 1; k++)
                            {
                                tmp += matrixA[jO + k].Conjugate()*matrixA[k*order + i].Conjugate();
                            }

                            // Form element of P
                            tau[j] = tmp/h;
                            f += (tmp/h)*matrixA[jO + i];
                        }

                        hh = f.Real/(h + h);

                        // Form the reduced A.
                        for (var j = 0; j < i; j++)
                        {
                            f = matrixA[j*order + i].Conjugate();
                            g = tau[j] - (hh*f);
                            tau[j] = g.Conjugate();

                            for (var k = 0; k <= j; k++)
                            {
                                matrixA[k*order + j] -= (f*tau[k]) + (g*matrixA[k*order + i]);
                            }
                        }
                    }

                    for (var k = 0; k < i; k++)
                    {
                        matrixA[k*order + i] *= scale;
                    }

                    tau[i - 1] = temp.Conjugate();
                }

                hh = d[i];
                d[i] = matrixA[i*order + i].Real;
                matrixA[i*order + i] = new Numerics.Complex32(hh, scale*(float) Math.Sqrt(h));
            }

            hh = d[0];
            d[0] = matrixA[0].Real;
            matrixA[0] = hh;
            e[0] = 0.0f;
        }
Ejemplo n.º 23
0
 public void MatrixFrom2DArrayIsCopy()
 {
     var matrix = new SparseMatrix(TestData2D["Singular3x3"]);
     matrix[0, 0] = new Complex32(10.0f, 1);
     Assert.AreEqual(new Complex32(1.0f, 1), TestData2D["Singular3x3"][0, 0]);
 }
Ejemplo n.º 24
0
        /// <summary>
        /// Nonsymmetric reduction from Hessenberg to real Schur form.
        /// </summary>
        /// <param name="vectorV">Data array of the eigenvectors</param>
        /// <param name="dataEv">Data array of matrix V (eigenvectors)</param>
        /// <param name="matrixH">Array for internal storage of nonsymmetric Hessenberg form.</param>
        /// <param name="order">Order of initial matrix</param>
        /// <remarks>This is derived from the Algol procedure hqr2,
        /// by Martin and Wilkinson, Handbook for Auto. Comp.,
        /// Vol.ii-Linear Algebra, and the corresponding
        /// Fortran subroutine in EISPACK.</remarks>
        internal static void NonsymmetricReduceHessenberToRealSchur(Numerics.Complex32[] vectorV, Numerics.Complex32[] dataEv, Numerics.Complex32[] matrixH, int order)
        {
            // Initialize
            var n = order - 1;
            var eps = (float) Precision.SingleMachinePrecision;

            float norm;
            Numerics.Complex32 x, y, z, exshift = Numerics.Complex32.Zero;

            // Outer loop over eigenvalue index
            var iter = 0;
            while (n >= 0)
            {
                // Look for single small sub-diagonal element
                var l = n;
                while (l > 0)
                {
                    var lm1 = l - 1;
                    var lm1O = lm1*order;
                    var lO = l*order;
                    var tst1 = Math.Abs(matrixH[lm1O + lm1].Real) + Math.Abs(matrixH[lm1O + lm1].Imaginary) + Math.Abs(matrixH[lO + l].Real) + Math.Abs(matrixH[lO + l].Imaginary);
                    if (Math.Abs(matrixH[lm1O + l].Real) < eps*tst1)
                    {
                        break;
                    }

                    l--;
                }

                var nm1 = n - 1;
                var nm1O = nm1*order;
                var nO = n*order;
                var nOn = nO + n;
                // Check for convergence
                // One root found
                if (l == n)
                {
                    matrixH[nOn] += exshift;
                    vectorV[n] = matrixH[nOn];
                    n--;
                    iter = 0;
                }
                else
                {
                    // Form shift
                    Numerics.Complex32 s;
                    if (iter != 10 && iter != 20)
                    {
                        s = matrixH[nOn];
                        x = matrixH[nO + nm1]*matrixH[nm1O + n].Real;

                        if (x.Real != 0.0f || x.Imaginary != 0.0f)
                        {
                            y = (matrixH[nm1O + nm1] - s)/2.0f;
                            z = ((y*y) + x).SquareRoot();
                            if ((y.Real*z.Real) + (y.Imaginary*z.Imaginary) < 0.0)
                            {
                                z *= -1.0f;
                            }

                            x /= y + z;
                            s = s - x;
                        }
                    }
                    else
                    {
                        // Form exceptional shift
                        s = Math.Abs(matrixH[nm1O + n].Real) + Math.Abs(matrixH[(n - 2)*order + nm1].Real);
                    }

                    for (var i = 0; i <= n; i++)
                    {
                        matrixH[i*order + i] -= s;
                    }

                    exshift += s;
                    iter++;

                    // Reduce to triangle (rows)
                    for (var i = l + 1; i <= n; i++)
                    {
                        var im1 = i - 1;
                        var im1O = im1*order;
                        var im1Oim1 = im1O + im1;
                        s = matrixH[im1O + i].Real;
                        norm = SpecialFunctions.Hypotenuse(matrixH[im1Oim1].Magnitude, s.Real);
                        x = matrixH[im1Oim1]/norm;
                        vectorV[i - 1] = x;
                        matrixH[im1Oim1] = norm;
                        matrixH[im1O + i] = new Numerics.Complex32(0.0f, s.Real/norm);

                        for (var j = i; j < order; j++)
                        {
                            var jO = j*order;
                            y = matrixH[jO + im1];
                            z = matrixH[jO + i];
                            matrixH[jO + im1] = (x.Conjugate()*y) + (matrixH[im1O + i].Imaginary*z);
                            matrixH[jO + i] = (x*z) - (matrixH[im1O + i].Imaginary*y);
                        }
                    }

                    s = matrixH[nOn];
                    if (s.Imaginary != 0.0f)
                    {
                        s /= matrixH[nOn].Magnitude;
                        matrixH[nOn] = matrixH[nOn].Magnitude;

                        for (var j = n + 1; j < order; j++)
                        {
                            matrixH[j*order + n] *= s.Conjugate();
                        }
                    }

                    // Inverse operation (columns).
                    for (var j = l + 1; j <= n; j++)
                    {
                        x = vectorV[j - 1];
                        var jO = j*order;
                        var jm1 = j - 1;
                        var jm1O = jm1*order;
                        var jm1Oj = jm1O + j;
                        for (var i = 0; i <= j; i++)
                        {
                            var jm1Oi = jm1O + i;
                            z = matrixH[jO + i];
                            if (i != j)
                            {
                                y = matrixH[jm1Oi];
                                matrixH[jm1Oi] = (x*y) + (matrixH[jm1O + j].Imaginary*z);
                            }
                            else
                            {
                                y = matrixH[jm1Oi].Real;
                                matrixH[jm1Oi] = new Numerics.Complex32((x.Real*y.Real) - (x.Imaginary*y.Imaginary) + (matrixH[jm1O + j].Imaginary*z.Real), matrixH[jm1Oi].Imaginary);
                            }

                            matrixH[jO + i] = (x.Conjugate()*z) - (matrixH[jm1O + j].Imaginary*y);
                        }

                        for (var i = 0; i < order; i++)
                        {
                            y = dataEv[((j - 1)*order) + i];
                            z = dataEv[(j*order) + i];
                            dataEv[jm1O + i] = (x*y) + (matrixH[jm1Oj].Imaginary*z);
                            dataEv[jO + i] = (x.Conjugate()*z) - (matrixH[jm1Oj].Imaginary*y);
                        }
                    }

                    if (s.Imaginary != 0.0f)
                    {
                        for (var i = 0; i <= n; i++)
                        {
                            matrixH[nO + i] *= s;
                        }

                        for (var i = 0; i < order; i++)
                        {
                            dataEv[nO + i] *= s;
                        }
                    }
                }
            }

            // All roots found.  
            // Backsubstitute to find vectors of upper triangular form
            norm = 0.0f;
            for (var i = 0; i < order; i++)
            {
                for (var j = i; j < order; j++)
                {
                    norm = Math.Max(norm, Math.Abs(matrixH[j*order + i].Real) + Math.Abs(matrixH[j*order + i].Imaginary));
                }
            }

            if (order == 1)
            {
                return;
            }

            if (norm == 0.0)
            {
                return;
            }

            for (n = order - 1; n > 0; n--)
            {
                var nO = n*order;
                var nOn = nO + n;
                x = vectorV[n];
                matrixH[nOn] = 1.0f;

                for (var i = n - 1; i >= 0; i--)
                {
                    z = 0.0f;
                    for (var j = i + 1; j <= n; j++)
                    {
                        z += matrixH[j*order + i]*matrixH[nO + j];
                    }

                    y = x - vectorV[i];
                    if (y.Real == 0.0f && y.Imaginary == 0.0f)
                    {
                        y = eps*norm;
                    }

                    matrixH[nO + i] = z/y;

                    // Overflow control
                    var tr = Math.Abs(matrixH[nO + i].Real) + Math.Abs(matrixH[nO + i].Imaginary);
                    if ((eps*tr)*tr > 1)
                    {
                        for (var j = i; j <= n; j++)
                        {
                            matrixH[nO + j] = matrixH[nO + j]/tr;
                        }
                    }
                }
            }

            // Back transformation to get eigenvectors of original matrix
            for (var j = order - 1; j > 0; j--)
            {
                var jO = j*order;
                for (var i = 0; i < order; i++)
                {
                    z = Numerics.Complex32.Zero;
                    for (var k = 0; k <= j; k++)
                    {
                        z += dataEv[(k*order) + i]*matrixH[jO + k];
                    }

                    dataEv[jO + i] = z;
                }
            }
        }
Ejemplo n.º 25
0
 /// <summary>
 /// Creates a vector from an array.
 /// </summary>
 /// <param name="data">The array to create this vector from.</param>
 /// <returns>The new vector. </returns>
 protected override Vector CreateVector(Complex32[] data)
 {
     return new SparseVector(data);
 }
Ejemplo n.º 26
0
        /// <summary>
        /// Solves a system of linear equations, <b>Ax = b</b>, with A EVD 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<Numerics.Complex32> input, Vector<Numerics.Complex32> result)
        {
            if (input == null)
            {
                throw new ArgumentNullException("input");
            }

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

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

            // Check that x is a column vector with n entries
            if (VectorEv.Count != result.Count)
            {
                throw new ArgumentException(Resources.ArgumentMatrixDimensions);
            }

            if (IsSymmetric)
            {
                // Symmetric case -> x = V * inv(λ) * VH * b;
                var order = VectorEv.Count;
                var tmp = new Numerics.Complex32[order];
                Numerics.Complex32 value;

                for (var j = 0; j < order; j++)
                {
                    value = 0;
                    if (j < order)
                    {
                        for (var i = 0; i < order; i++)
                        {
                            value += ((DenseMatrix) MatrixEv).Values[(j*order) + i].Conjugate()*input[i];
                        }

                        value /= (float) VectorEv[j].Real;
                    }

                    tmp[j] = value;
                }

                for (var j = 0; j < order; j++)
                {
                    value = 0;
                    for (var i = 0; i < order; i++)
                    {
                        value += ((DenseMatrix) MatrixEv).Values[(i*order) + j]*tmp[i];
                    }

                    result[j] = value;
                }
            }
            else
            {
                throw new ArgumentException(Resources.ArgumentMatrixSymmetric);
            }
        }
Ejemplo n.º 27
0
        public void CheckSparseMechanismBySettingValues()
        {
            var vector = new SparseVector(10000);

            // Add non-zero elements
            vector[200] = new Complex32(1.5f, 1);
            Assert.AreEqual(new Complex32(1.5f, 1), vector[200]);
            Assert.AreEqual(1, vector.NonZerosCount);

            vector[500] = new Complex32(3.5f, 1);
            Assert.AreEqual(new Complex32(3.5f, 1), vector[500]);
            Assert.AreEqual(2, vector.NonZerosCount);

            vector[800] = new Complex32(5.5f, 1);
            Assert.AreEqual(new Complex32(5.5f, 1), vector[800]);
            Assert.AreEqual(3, vector.NonZerosCount);

            vector[0] = new Complex32(7.5f, 1);
            Assert.AreEqual(new Complex32(7.5f, 1), vector[0]);
            Assert.AreEqual(4, vector.NonZerosCount);

            // Remove non-zero elements
            vector[200] = Complex32.Zero;
            Assert.AreEqual(Complex32.Zero, vector[200]);
            Assert.AreEqual(3, vector.NonZerosCount);

            vector[500] = Complex32.Zero;
            Assert.AreEqual(Complex32.Zero, vector[500]);
            Assert.AreEqual(2, vector.NonZerosCount);

            vector[800] = Complex32.Zero;
            Assert.AreEqual(Complex32.Zero, vector[800]);
            Assert.AreEqual(1, vector.NonZerosCount);

            vector[0] = Complex32.Zero;
            Assert.AreEqual(Complex32.Zero, vector[0]);
            Assert.AreEqual(0, vector.NonZerosCount);
        }
Ejemplo n.º 28
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>
 protected internal override void At(int index, Complex32 value)
 {
     this[index] = value;
 }
 /// <summary>
 /// Creates a vector from an array.
 /// </summary>
 /// <param name="data">The array to create this vector from.</param>
 /// <returns>The new vector. </returns>
 protected override Vector CreateVector(Complex32[] data)
 {
     return SparseVector.OfEnumerable(data);
 }
Ejemplo n.º 30
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 <Numerics.Complex32> input, Matrix <Numerics.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 (VectorEv.Count != input.RowCount)
            {
                throw new ArgumentException(Resources.ArgumentMatrixSameRowDimension);
            }

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

            if (IsSymmetric)
            {
                var order = VectorEv.Count;
                var tmp   = new Numerics.Complex32[order];

                for (var k = 0; k < order; k++)
                {
                    for (var j = 0; j < order; j++)
                    {
                        Numerics.Complex32 value = 0.0f;
                        if (j < order)
                        {
                            for (var i = 0; i < order; i++)
                            {
                                value += ((DenseMatrix)MatrixEv).Values[(j * order) + i].Conjugate() * input.At(i, k);
                            }

                            value /= (float)VectorEv[j].Real;
                        }

                        tmp[j] = value;
                    }

                    for (var j = 0; j < order; j++)
                    {
                        Numerics.Complex32 value = 0.0f;
                        for (var i = 0; i < order; i++)
                        {
                            value += ((DenseMatrix)MatrixEv).Values[(i * order) + j] * tmp[i];
                        }

                        result.At(j, k, value);
                    }
                }
            }
            else
            {
                throw new ArgumentException(Resources.ArgumentMatrixSymmetric);
            }
        }
Ejemplo n.º 31
0
        /// <summary>
        /// Nonsymmetric reduction to Hessenberg form.
        /// </summary>
        /// <param name="dataEv">Data array of matrix V (eigenvectors)</param>
        /// <param name="matrixH">Array for internal storage of nonsymmetric Hessenberg form.</param>
        /// <param name="order">Order of initial matrix</param>
        /// <remarks>This is derived from the Algol procedures orthes and ortran,
        /// by Martin and Wilkinson, Handbook for Auto. Comp.,
        /// Vol.ii-Linear Algebra, and the corresponding
        /// Fortran subroutines in EISPACK.</remarks>
        internal static void NonsymmetricReduceToHessenberg(Numerics.Complex32[] dataEv, Numerics.Complex32[] matrixH, int order)
        {
            var ort = new Numerics.Complex32[order];

            for (var m = 1; m < order - 1; m++)
            {
                // Scale column.
                var scale = 0.0f;
                var mm1O = (m - 1)*order;
                for (var i = m; i < order; i++)
                {
                    scale += Math.Abs(matrixH[mm1O + i].Real) + Math.Abs(matrixH[mm1O + i].Imaginary);
                }

                if (scale != 0.0f)
                {
                    // Compute Householder transformation.
                    var h = 0.0f;
                    for (var i = order - 1; i >= m; i--)
                    {
                        ort[i] = matrixH[mm1O + i]/scale;
                        h += ort[i].MagnitudeSquared;
                    }

                    var g = (float) Math.Sqrt(h);
                    if (ort[m].Magnitude != 0)
                    {
                        h = h + (ort[m].Magnitude*g);
                        g /= ort[m].Magnitude;
                        ort[m] = (1.0f + g)*ort[m];
                    }
                    else
                    {
                        ort[m] = g;
                        matrixH[mm1O + m] = scale;
                    }

                    // Apply Householder similarity transformation
                    // H = (I-u*u'/h)*H*(I-u*u')/h)
                    for (var j = m; j < order; j++)
                    {
                        var f = Numerics.Complex32.Zero;
                        var jO = j*order;
                        for (var i = order - 1; i >= m; i--)
                        {
                            f += ort[i].Conjugate()*matrixH[jO + i];
                        }

                        f = f/h;
                        for (var i = m; i < order; i++)
                        {
                            matrixH[jO + i] -= f*ort[i];
                        }
                    }

                    for (var i = 0; i < order; i++)
                    {
                        var f = Numerics.Complex32.Zero;
                        for (var j = order - 1; j >= m; j--)
                        {
                            f += ort[j]*matrixH[j*order + i];
                        }

                        f = f/h;
                        for (var j = m; j < order; j++)
                        {
                            matrixH[j*order + i] -= f*ort[j].Conjugate();
                        }
                    }

                    ort[m] = scale*ort[m];
                    matrixH[mm1O + m] *= -g;
                }
            }

            // Accumulate transformations (Algol's ortran).
            for (var i = 0; i < order; i++)
            {
                for (var j = 0; j < order; j++)
                {
                    dataEv[(j*order) + i] = i == j ? Numerics.Complex32.One : Numerics.Complex32.Zero;
                }
            }

            for (var m = order - 2; m >= 1; m--)
            {
                var mm1O = (m - 1)*order;
                var mm1Om = mm1O + m;
                if (matrixH[mm1Om] != Numerics.Complex32.Zero && ort[m] != Numerics.Complex32.Zero)
                {
                    var norm = (matrixH[mm1Om].Real*ort[m].Real) + (matrixH[mm1Om].Imaginary*ort[m].Imaginary);

                    for (var i = m + 1; i < order; i++)
                    {
                        ort[i] = matrixH[mm1O + i];
                    }

                    for (var j = m; j < order; j++)
                    {
                        var g = Numerics.Complex32.Zero;
                        for (var i = m; i < order; i++)
                        {
                            g += ort[i].Conjugate()*dataEv[(j*order) + i];
                        }

                        // Double division avoids possible underflow
                        g /= norm;
                        for (var i = m; i < order; i++)
                        {
                            dataEv[(j*order) + i] += g*ort[i];
                        }
                    }
                }
            }

            // Create real subdiagonal elements.
            for (var i = 1; i < order; i++)
            {
                var im1 = i - 1;
                var im1O = im1*order;
                var im1Oi = im1O + i;
                var iO = i*order;
                if (matrixH[im1Oi].Imaginary != 0.0f)
                {
                    var y = matrixH[im1Oi]/matrixH[im1Oi].Magnitude;
                    matrixH[im1Oi] = matrixH[im1Oi].Magnitude;
                    for (var j = i; j < order; j++)
                    {
                        matrixH[j*order + i] *= y.Conjugate();
                    }

                    for (var j = 0; j <= Math.Min(i + 1, order - 1); j++)
                    {
                        matrixH[iO + j] *= y;
                    }

                    for (var j = 0; j < order; j++)
                    {
                        dataEv[(i*order) + j] *= y;
                    }
                }
            }
        }
Ejemplo n.º 32
0
 public virtual void SetColumnWithArrayUnequalLengthThrowsArgumentException()
 {
     var array = new Complex32[] { 1, 2, 3, 4, 5 };
     Assert.Throws<ArgumentException>(() => TestMatrices["Singular3x3"].SetColumn(1, array));
 }
Ejemplo n.º 33
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<Numerics.Complex32> input, Matrix<Numerics.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 (VectorEv.Count != input.RowCount)
            {
                throw new ArgumentException(Resources.ArgumentMatrixSameRowDimension);
            }

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

            if (IsSymmetric)
            {
                var order = VectorEv.Count;
                var tmp = new Numerics.Complex32[order];

                for (var k = 0; k < order; k++)
                {
                    for (var j = 0; j < order; j++)
                    {
                        Numerics.Complex32 value = 0.0f;
                        if (j < order)
                        {
                            for (var i = 0; i < order; i++)
                            {
                                value += ((DenseMatrix) MatrixEv).Values[(j*order) + i].Conjugate()*input.At(i, k);
                            }

                            value /= (float) VectorEv[j].Real;
                        }

                        tmp[j] = value;
                    }

                    for (var j = 0; j < order; j++)
                    {
                        Numerics.Complex32 value = 0.0f;
                        for (var i = 0; i < order; i++)
                        {
                            value += ((DenseMatrix) MatrixEv).Values[(i*order) + j]*tmp[i];
                        }

                        result.At(j, k, value);
                    }
                }
            }
            else
            {
                throw new ArgumentException(Resources.ArgumentMatrixSymmetric);
            }
        }
Ejemplo n.º 34
0
 public void SetDiagonalArrayWithUnequalLengthThrowsArgumentException()
 {
     var array = new Complex32[] { 1, 2, 3 };
     Assert.Throws<ArgumentException>(() => TestMatrices["Wide2x3"].SetDiagonal(array));
 }
Ejemplo n.º 35
0
 /// <summary>
 /// Initializes a new instance of the <see cref="UserDefinedVector"/> class for an array.
 /// </summary>
 /// <param name="data">The array to create this vector from.</param>
 public UserDefinedVector(Complex32[] data) : base(data.Length)
 {
     _data = (Complex32[])data.Clone();
 }
Ejemplo n.º 36
0
        public virtual void CanSetColumnWithArray([Values("Singular3x3", "Square3x3", "Tall3x2", "Wide2x3")] string name, [Values(new float[] { 1, 2, 3 }, new float[] { 1, 2, 3 }, new float[] { 1, 2, 3 }, new float[] { 1, 2 })] float[] real)
        {
            var column = new Complex32[real.Length];
            for (var i = 0; i < real.Length; i++)
            {
                column[i] = new Complex32(real[i], 1);
            }

            var matrix = TestMatrices[name];
            for (var i = 0; i < matrix.ColumnCount; i++)
            {
                matrix.SetColumn(i, column);
                for (var j = 0; j < matrix.RowCount; j++)
                {
                    Assert.AreEqual(matrix[j, i], column[j]);
                }
            }
        }
Ejemplo n.º 37
0
 public void CanFindAbsoluteMinimum()
 {
     var source = CreateVector(Data);
     var expected = new Complex32(1, 1).Magnitude;
     var actual = source.AbsoluteMinimum();
     Assert.AreEqual(expected, actual.Real);
 }
Ejemplo n.º 38
0
        public void CanSetDiagonalVector([Values("Square3x3", "Wide2x3", "Tall3x2")] string name, [Values(new float[] { 1, 2, 3 }, new float[] { 1, 2 }, new float[] { 1, 2 })] float[] real)
        {
            var diagonal = new Complex32[real.Length];
            for (var i = 0; i < real.Length; i++)
            {
                diagonal[i] = new Complex32(real[i], 1);
            }

            var matrix = TestMatrices[name];
            var vector = CreateVector(diagonal);
            matrix.SetDiagonal(vector);

            var min = Math.Min(matrix.ColumnCount, matrix.RowCount);
            Assert.AreEqual(diagonal.Length, min);

            for (var i = 0; i < vector.Count; i++)
            {
                Assert.AreEqual(vector[i], matrix[i, i]);
            }
        }
        public void CanOperatorLeftMultiplyWithComplex([Values(0, 1, 2.2f)] float real)
        {
            var value = new Complex32(real, 1.0f);
            var matrix = TestMatrices["Singular3x3"];
            var clone = value * matrix;

            for (var i = 0; i < matrix.RowCount; i++)
            {
                for (var j = 0; j < matrix.ColumnCount; j++)
                {
                    Assert.AreEqual(value * matrix[i, j], clone[i, j]);
                }
            }
        }
Ejemplo n.º 40
0
        public virtual void CanSetRowWithVector([Values("Singular3x3", "Square3x3", "Tall3x2", "Wide2x3")] string name, [Values(new float[] { 1, 2, 3 }, new float[] { 1, 2, 3 }, new float[] { 1, 2 }, new float[] { 1, 2, 3 })] float[] real)
        {
            var row = new Complex32[real.Length];
            for (var i = 0; i < real.Length; i++)
            {
                row[i] = new Complex32(real[i], 1);
            }

            var matrix = TestMatrices[name];
            var rowVector = CreateVector(row);
            for (var i = 0; i < matrix.RowCount; i++)
            {
                matrix.SetRow(i, row);
                for (var j = 0; j < matrix.ColumnCount; j++)
                {
                    Assert.AreEqual(matrix[i, j], rowVector[j]);
                }
            }
        }