Example #1
0
        /// <summary>
        /// Returns the Pearson correlation coefficient of two sets of values.
        /// </summary>
        /// <param name="a">An array of complex numbers.</param>
        /// <param name="b">An array of complex numbers.</param>
        /// <returns>The Pearson correlation coefficient of the elements of a and b.</returns>
        /// <exception cref="System.ArgumentException">
        /// The length of the array a does not match the length of the array b.
        /// </exception>
        public static Complex Correlation(IList <Complex> a, IList <Complex> b)
        {
            if (a.Count != b.Count)
            {
                throw new ArgumentException("The lengths of the two arrays do not match.");
            }

            Complex mean_a = Mean(a);
            Complex mean_b = Mean(b);

            Complex sum  = Complex.Zero;
            double  sum1 = 0.0;
            double  sum2 = 0.0;

            for (int i = 0; i < a.Count; i++)
            {
                Complex c1 = a[i] - mean_a;
                Complex c2 = b[i] - mean_b;

                sum  += Complex.ConjugateMultiply(c2, c1);
                sum1 += Complex.AbsSquared(c1);
                sum2 += Complex.AbsSquared(c2);
            }

            return(sum / Math.Sqrt(sum1 * sum2));
        }
Example #2
0
        /// <summary>
        /// Returns the population variance of the elements of an array.
        /// </summary>
        /// <param name="v">An array of complex numbers.</param>
        /// <returns>The population variance of the elements of v.</returns>
        public static double PopulationVariance(IEnumerable <Complex> v)
        {
            int     count = 0;
            double  sum   = 0.0;
            Complex mean  = Mean(v);

            foreach (Complex item in v)
            {
                sum += Complex.AbsSquared(item - mean);
                count++;
            }

            return(sum / count);
        }
Example #3
0
        /// <summary>
        /// Returns the sample variance of the elements of an array.
        /// </summary>
        /// <param name="v">An array of complex numbers.</param>
        /// <returns>The sample variance of the elements of v.</returns>
        public static double SampleVariance(IEnumerable <Complex> v)
        {
            int     count = 0;
            double  sum   = 0.0;
            Complex mean  = Mean(v);

            foreach (Complex item in v)
            {
                sum += Complex.AbsSquared(item - mean);
                count++;
            }

            if (count == 1)
            {
                return(0.0);
            }
            return(sum / (count - 1));
        }
Example #4
0
        public static Complex InfiniteProduct(Func <Complex, Complex> term, int m, double relativeTolerance)
        {
            double tolsq = relativeTolerance * relativeTolerance;

            Complex product = Complex.One;
            Complex termValue;

            for (int i = m; i < _maxIters; i++)
            {
                termValue = term(i);
                product  *= termValue;

                if (Complex.AbsSquared(termValue / product) <= tolsq)
                {
                    return(product);
                }
            }

            throw new NotConvergenceException();
        }
Example #5
0
        public static Complex InfiniteSummation(Func <Complex, Complex> term, int m, double relativeTolerance)
        {
            double tolsq = relativeTolerance * relativeTolerance;

            Complex sum = Complex.Zero;
            Complex termValue;

            for (int i = m; i <= _maxIters; i++)
            {
                termValue = term(i);
                sum      += termValue;

                if (Complex.AbsSquared(termValue / sum) <= tolsq)
                {
                    return(sum);
                }
            }

            throw new NotConvergenceException();
        }
Example #6
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(Complex[] matrixA, double[] d, double[] e, Complex[] tau, int order)
        {
            double hh;

            tau[order - 1] = Complex.One;

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

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

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

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

                    Complex g = Math.Sqrt(h);
                    e[i] = scale * g.Re;

                    Complex temp;
                    var     im1Oi = (i - 1) * order + i;
                    var     f     = matrixA[im1Oi];
                    if (f.Modulus != 0)
                    {
                        temp            = -(Complex.Conjugate(matrixA[im1Oi]) * Complex.Conjugate(tau[i])) / f.Modulus;
                        h              += f.Modulus * g.Re;
                        g               = 1.0 + (g / f.Modulus);
                        matrixA[im1Oi] *= g;
                    }
                    else
                    {
                        temp           = -Complex.Conjugate(tau[i]);
                        matrixA[im1Oi] = g;
                    }

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

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

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

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

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

                            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] = Complex.Conjugate(temp);
                }

                hh   = d[i];
                d[i] = matrixA[i * order + i].Re;
                matrixA[i * order + i] = new Complex(hh, scale * Math.Sqrt(h));
            }

            hh         = d[0];
            d[0]       = matrixA[0].Re;
            matrixA[0] = hh;
            e[0]       = 0.0;
        }
Example #7
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(Complex[] dataEv, Complex[] matrixH, int order)
        {
            var ort = new Complex[order];

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

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

                    var g = Math.Sqrt(h);
                    if (ort[m].Modulus != 0)
                    {
                        h      = h + (ort[m].Modulus * g);
                        g     /= ort[m].Modulus;
                        ort[m] = (1.0 + 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  = Complex.Zero;
                        var jO = j * order;
                        for (var i = order - 1; i >= m; i--)
                        {
                            f += Complex.Conjugate(ort[i]) * 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 = Complex.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 * Complex.Conjugate(ort[j]);
                        }
                    }

                    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 ? Complex.One : Complex.Zero;
                }
            }

            for (var m = order - 2; m >= 1; m--)
            {
                var mm1O  = (m - 1) * order;
                var mm1Om = mm1O + m;
                if (matrixH[mm1Om] != Complex.Zero && ort[m] != Complex.Zero)
                {
                    var norm = (matrixH[mm1Om].Re * ort[m].Re) + (matrixH[mm1Om].Im * ort[m].Im);

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

                    for (var j = m; j < order; j++)
                    {
                        var g = Complex.Zero;
                        for (var i = m; i < order; i++)
                        {
                            g += Complex.Conjugate(ort[i]) * 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].Im != 0.0)
                {
                    var y = matrixH[im1Oi] / matrixH[im1Oi].Modulus;
                    matrixH[im1Oi] = matrixH[im1Oi].Modulus;
                    for (var j = i; j < order; j++)
                    {
                        matrixH[j * order + i] *= Complex.Conjugate(y);
                    }

                    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;
                    }
                }
            }
        }