/// <inheritdoc/> public override RealVector ebeDivide(RealVector v) { if (v is ArrayRealVector) { double[] vData = ((ArrayRealVector)v).data; int dim = vData.Length; checkVectorDimensions(dim); ArrayRealVector result = new ArrayRealVector(dim); double[] resultData = result.data; for (int i = 0; i < dim; i++) { resultData[i] = data[i] / vData[i]; } return(result); } else { checkVectorDimensions(v); double[] outp = (Double[])data.Clone(); for (int i = 0; i < data.Length; i++) { outp[i] /= v.getEntry(i); } return(new ArrayRealVector(outp, false)); } }
/// <summary> /// Solves the linear equation A × X = B for symmetric matrices A. /// <para> /// This method only finds exact linear solutions, i.e. solutions for /// which ||A × X - B|| is exactly 0. /// </para> /// </summary> /// <param name="b">Right-hand side of the equation A × X = B.</param> /// <returns>Vector X that minimizes the two norm of A × X - B.</returns> /// <exception cref=DimensionMismatchException""> if the matrices dimensions do not /// match.</exception> /// <exception cref="SingularMatrixException"> if the decomposed matrix is singular. /// </exception> public RealVector solve(RealVector b) { if (!isNonSingular()) { throw new SingularMatrixException(); } int m = realEigenvalues.Length; if (b.getDimension() != m) { throw new DimensionMismatchException(b.getDimension(), m); } double[] bp = new double[m]; for (int i = 0; i < m; ++i) { ArrayRealVector v = eigenvectors[i]; double[] vData = v.getDataRef(); double s = v.dotProduct(b) / realEigenvalues[i]; for (int j = 0; j < m; ++j) { bp[j] += s * vData[j]; } } return(new ArrayRealVector(bp, false)); }
/// <inheritdoc/> public new ArrayRealVector subtract(RealVector v) { if (v is ArrayRealVector) { double[] vData = ((ArrayRealVector)v).data; int dim = vData.Length; checkVectorDimensions(dim); ArrayRealVector result = new ArrayRealVector(dim); double[] resultData = result.data; for (int i = 0; i < dim; i++) { resultData[i] = data[i] - vData[i]; } return(result); } else { checkVectorDimensions(v); double[] outp = (Double[])data.Clone(); IEnumerator <Entry> it = v.iterator(); while (it.MoveNext()) { Entry e = it.Current; outp[e.getIndex()] -= e.getValue(); } return(new ArrayRealVector(outp, false)); } }
/// <summary> /// Construct a vector by appending one vector to another vector. /// </summary> /// <param name="v1">First vector (will be put in front of the new vector).</param> /// <param name="v2">Second vector (will be put at back of the new vector).</param> public ArrayRealVector(double[] v1, ArrayRealVector v2) { int l1 = v1.Length; int l2 = v2.getDimension(); data = new double[l1 + l2]; Array.Copy(v1, 0, data, 0, l1); Array.Copy(v2.data, 0, data, l1, l2); }
/// <summary> /// Parse a string to produce a <see cref="RealVector"/> object. /// </summary> /// <param name="source">String to parse.</param> /// <returns>the parsed <see cref="RealVector"/> object.</returns> /// <exception cref="MathParseException"> if the beginning of the specified string /// cannot be parsed.</exception> public ArrayRealVector parse(String source) { Int32 parsePosition = 0; ArrayRealVector result = parse(source, parsePosition); if (parsePosition == 0) { throw new MathParseException(source, parsePosition, typeof(ArrayRealVector)); } return(result); }
/// <summary> /// Construct a vector by appending one vector to another vector. /// </summary> /// <param name="v1">First vector (will be put in front of the new vector).</param> /// <param name="v2">Second vector (will be put at back of the new vector).</param> public ArrayRealVector(RealVector v1, ArrayRealVector v2) { int l1 = v1.getDimension(); int l2 = v2.data.Length; data = new double[l1 + l2]; for (int i = 0; i < l1; ++i) { data[i] = v1.getEntry(i); } Array.Copy(v2.data, 0, data, l1, l2); }
/// <summary> /// Construct a vector by appending one vector to another vector. /// </summary> /// <param name="v1">First vector (will be put in front of the new vector).</param> /// <param name="v2">Second vector (will be put at back of the new vector).</param> public ArrayRealVector(ArrayRealVector v1, RealVector v2) { int l1 = v1.data.Length; int l2 = v2.getDimension(); data = new double[l1 + l2]; Array.Copy(v1.data, 0, data, 0, l1); for (int i = 0; i < l2; ++i) { data[l1 + i] = v2.getEntry(i); } }
/// <inheritdoc/> public RealMatrix solve(RealMatrix b) { if (!isNonSingular()) { throw new SingularMatrixException(); } int m = realEigenvalues.Length; if (b.getRowDimension() != m) { throw new DimensionMismatchException(b.getRowDimension(), m); } int nColB = b.getColumnDimension(); double[][] bp = new double[m][]; double[] tmpCol = new double[m]; for (int k = 0; k < nColB; ++k) { for (int i = 0; i < m; ++i) { tmpCol[i] = b.getEntry(i, k); bp[i][k] = 0; } for (int i = 0; i < m; ++i) { ArrayRealVector v = eigenvectors[i]; double[] vData = v.getDataRef(); double s = 0; for (int j = 0; j < m; ++j) { s += v.getEntry(j) * tmpCol[j]; } s /= realEigenvalues[i]; for (int j = 0; j < m; ++j) { bp[j][k] += s * vData[j]; } } } return(new Array2DRowRealMatrix(bp, false)); }
/// <inheritdoc/> public override RealVector getSubVector(int index, int n) { if (n < 0) { throw new NotPositiveException <Int32>(new LocalizedFormats("NUMBER_OF_ELEMENTS_SHOULD_BE_POSITIVE"), n); } ArrayRealVector outp = new ArrayRealVector(n); try { Array.Copy(data, index, outp.data, 0, n); } catch (IndexOutOfRangeException) { checkIndex(index); checkIndex(index + n - 1); } return(outp); }
/// <summary> /// Construct a vector by appending a vector to this vector. /// </summary> /// <param name="v">Vector to append to this one.</param> /// <returns>a new vector.</returns> public ArrayRealVector append(ArrayRealVector v) { return(new ArrayRealVector(this, v)); }
/// <summary> /// Construct a vector by appending one vector to another vector. /// </summary> /// <param name="v1">First vector (will be put in front of the new vector).</param> /// <param name="v2">Second vector (will be put at back of the new vector).</param> public ArrayRealVector(ArrayRealVector v1, ArrayRealVector v2) { data = new double[v1.data.Length + v2.data.Length]; Array.Copy(v1.data, 0, data, 0, v1.data.Length); Array.Copy(v2.data, 0, data, v1.data.Length, v2.data.Length); }
/// <summary> /// Construct a vector from another vector. /// </summary> /// <param name="v">Vector to copy.</param> /// <param name="deep">If <c>true</c> perform a deep copy, otherwise perform a /// shallow copy.</param> public ArrayRealVector(ArrayRealVector v, Boolean deep) { data = deep ? (Double[])v.data.Clone() : v.data; }
/// <summary> /// Construct a vector from another vector, using a deep copy. /// </summary> /// <param name="v">Vector to copy.</param> /// <exception cref="NullArgumentException"> if <c>v</c> is <c>null</c>.</exception> public ArrayRealVector(ArrayRealVector v) : this(v, true) { }
/// <summary> /// Find eigenvectors from a matrix transformed to Schur form. /// </summary> /// <param name="schur">the schur transformation of the matrix</param> /// <exception cref="MathArithmeticException"> if the Schur form has a norm of zero /// </exception> private void findEigenVectorsFromSchur(SchurTransformer schur) { double[][] matrixT = schur.getT().getData(); double[][] matrixP = schur.getP().getData(); int n = matrixT.Length; // compute matrix norm double norm = 0.0; for (int i = 0; i < n; i++) { for (int j = FastMath.max(i - 1, 0); j < n; j++) { norm += FastMath.abs(matrixT[i][j]); } } // we can not handle a matrix with zero norm if (Precision.equals(norm, 0.0, EPSILON)) { throw new MathArithmeticException(new LocalizedFormats("ZERO_NORM")); } // Backsubstitute to find vectors of upper triangular form double r = 0.0; double s = 0.0; double z = 0.0; for (int idx = n - 1; idx >= 0; idx--) { double p = realEigenvalues[idx]; double q = imagEigenvalues[idx]; if (Precision.equals(q, 0.0)) { // Real vector int l = idx; matrixT[idx][idx] = 1.0; for (int i = idx - 1; i >= 0; i--) { double w = matrixT[i][i] - p; r = 0.0; for (int j = l; j <= idx; j++) { r += matrixT[i][j] * matrixT[j][idx]; } if (Precision.compareTo(imagEigenvalues[i], 0.0, EPSILON) < 0) { z = w; s = r; } else { l = i; if (Precision.equals(imagEigenvalues[i], 0.0)) { if (w != 0.0) { matrixT[i][idx] = -r / w; } else { matrixT[i][idx] = -r / (Precision.EPSILON * norm); } } else { // Solve real equations double x = matrixT[i][i + 1]; double y = matrixT[i + 1][i]; q = (realEigenvalues[i] - p) * (realEigenvalues[i] - p) + imagEigenvalues[i] * imagEigenvalues[i]; double t = (x * s - z * r) / q; matrixT[i][idx] = t; if (FastMath.abs(x) > FastMath.abs(z)) { matrixT[i + 1][idx] = (-r - w * t) / x; } else { matrixT[i + 1][idx] = (-s - y * t) / z; } } // Overflow control double tt = FastMath.abs(matrixT[i][idx]); if ((Precision.EPSILON * tt) * tt > 1) { for (int j = i; j <= idx; j++) { matrixT[j][idx] /= tt; } } } } } else if (q < 0.0) { // Complex vector int l = idx - 1; // Last vector component imaginary so matrix is triangular if (FastMath.abs(matrixT[idx][idx - 1]) > FastMath.abs(matrixT[idx - 1][idx])) { matrixT[idx - 1][idx - 1] = q / matrixT[idx][idx - 1]; matrixT[idx - 1][idx] = -(matrixT[idx][idx] - p) / matrixT[idx][idx - 1]; } else { Complex result = cdiv(0.0, -matrixT[idx - 1][idx], matrixT[idx - 1][idx - 1] - p, q); matrixT[idx - 1][idx - 1] = result.getReal(); matrixT[idx - 1][idx] = result.getImaginary(); } matrixT[idx][idx - 1] = 0.0; matrixT[idx][idx] = 1.0; for (int i = idx - 2; i >= 0; i--) { double ra = 0.0; double sa = 0.0; for (int j = l; j <= idx; j++) { ra += matrixT[i][j] * matrixT[j][idx - 1]; sa += matrixT[i][j] * matrixT[j][idx]; } double w = matrixT[i][i] - p; if (Precision.compareTo(imagEigenvalues[i], 0.0, EPSILON) < 0) { z = w; r = ra; s = sa; } else { l = i; if (Precision.equals(imagEigenvalues[i], 0.0)) { Complex c = cdiv(-ra, -sa, w, q); matrixT[i][idx - 1] = c.getReal(); matrixT[i][idx] = c.getImaginary(); } else { // Solve complex equations double x = matrixT[i][i + 1]; double y = matrixT[i + 1][i]; double vr = (realEigenvalues[i] - p) * (realEigenvalues[i] - p) + imagEigenvalues[i] * imagEigenvalues[i] - q * q; double vi = (realEigenvalues[i] - p) * 2.0 * q; if (Precision.equals(vr, 0.0) && Precision.equals(vi, 0.0)) { vr = Precision.EPSILON * norm * (FastMath.abs(w) + FastMath.abs(q) + FastMath.abs(x) + FastMath.abs(y) + FastMath.abs(z)); } Complex c = cdiv(x * r - z * ra + q * sa, x * s - z * sa - q * ra, vr, vi); matrixT[i][idx - 1] = c.getReal(); matrixT[i][idx] = c.getImaginary(); if (FastMath.abs(x) > (FastMath.abs(z) + FastMath.abs(q))) { matrixT[i + 1][idx - 1] = (-ra - w * matrixT[i][idx - 1] + q * matrixT[i][idx]) / x; matrixT[i + 1][idx] = (-sa - w * matrixT[i][idx] - q * matrixT[i][idx - 1]) / x; } else { Complex c2 = cdiv(-r - y * matrixT[i][idx - 1], -s - y * matrixT[i][idx], z, q); matrixT[i + 1][idx - 1] = c2.getReal(); matrixT[i + 1][idx] = c2.getImaginary(); } } // Overflow control double t = FastMath.max(FastMath.abs(matrixT[i][idx - 1]), FastMath.abs(matrixT[i][idx])); if ((Precision.EPSILON * t) * t > 1) { for (int j = i; j <= idx; j++) { matrixT[j][idx - 1] /= t; matrixT[j][idx] /= t; } } } } } } // Back transformation to get eigenvectors of original matrix for (int j = n - 1; j >= 0; j--) { for (int i = 0; i <= n - 1; i++) { z = 0.0; for (int k = 0; k <= FastMath.min(j, n - 1); k++) { z += matrixP[i][k] * matrixT[k][j]; } matrixP[i][j] = z; } } eigenvectors = new ArrayRealVector[n]; double[] tmp = new double[n]; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { tmp[j] = matrixP[j][i]; } eigenvectors[i] = new ArrayRealVector(tmp); } }
/// <summary> /// Find eigenvalues and eigenvectors (Dubrulle et al., 1971) /// </summary> /// <param name="householderMatrix">Householder matrix of the transformation /// to tridiagonal form.</param> private void findEigenVectors(double[][] householderMatrix) { double[][] z = (Double[][])householderMatrix.Clone(); int n = main.Length; realEigenvalues = new double[n]; imagEigenvalues = new double[n]; double[] e = new double[n]; for (int i = 0; i < n - 1; i++) { realEigenvalues[i] = main[i]; e[i] = secondary[i]; } realEigenvalues[n - 1] = main[n - 1]; e[n - 1] = 0; // Determine the largest main and secondary value in absolute term. double maxAbsoluteValue = 0; for (int i = 0; i < n; i++) { if (FastMath.abs(realEigenvalues[i]) > maxAbsoluteValue) { maxAbsoluteValue = FastMath.abs(realEigenvalues[i]); } if (FastMath.abs(e[i]) > maxAbsoluteValue) { maxAbsoluteValue = FastMath.abs(e[i]); } } // Make null any main and secondary value too small to be significant if (maxAbsoluteValue != 0) { for (int i = 0; i < n; i++) { if (FastMath.abs(realEigenvalues[i]) <= Precision.EPSILON * maxAbsoluteValue) { realEigenvalues[i] = 0; } if (FastMath.abs(e[i]) <= Precision.EPSILON * maxAbsoluteValue) { e[i] = 0; } } } for (int j = 0; j < n; j++) { int its = 0; int m; do { for (m = j; m < n - 1; m++) { double delta = FastMath.abs(realEigenvalues[m]) + FastMath.abs(realEigenvalues[m + 1]); if (FastMath.abs(e[m]) + delta == delta) { break; } } if (m != j) { if (its == maxIter) { throw new MaxCountExceededException <Byte>(new LocalizedFormats("CONVERGENCE_FAILED"), maxIter); } its++; double q = (realEigenvalues[j + 1] - realEigenvalues[j]) / (2 * e[j]); double t = FastMath.sqrt(1 + q * q); if (q < 0.0) { q = realEigenvalues[m] - realEigenvalues[j] + e[j] / (q - t); } else { q = realEigenvalues[m] - realEigenvalues[j] + e[j] / (q + t); } double u = 0.0; double s = 1.0; double c = 1.0; int i; for (i = m - 1; i >= j; i--) { double p = s * e[i]; double h = c * e[i]; if (FastMath.abs(p) >= FastMath.abs(q)) { c = q / p; t = FastMath.sqrt(c * c + 1.0); e[i + 1] = p * t; s = 1.0 / t; c *= s; } else { s = p / q; t = FastMath.sqrt(s * s + 1.0); e[i + 1] = q * t; c = 1.0 / t; s *= c; } if (e[i + 1] == 0.0) { realEigenvalues[i + 1] -= u; e[m] = 0.0; break; } q = realEigenvalues[i + 1] - u; t = (realEigenvalues[i] - q) * s + 2.0 * c * h; u = s * t; realEigenvalues[i + 1] = q + u; q = c * t - h; for (int ia = 0; ia < n; ia++) { p = z[ia][i + 1]; z[ia][i + 1] = s * z[ia][i] + c * p; z[ia][i] = c * z[ia][i] - s * p; } } if (t == 0.0 && i >= j) { continue; } realEigenvalues[j] -= u; e[j] = q; e[m] = 0.0; } } while (m != j); } //Sort the eigen values (and vectors) in increase order for (int i = 0; i < n; i++) { int k = i; double p = realEigenvalues[i]; for (int j = i + 1; j < n; j++) { if (realEigenvalues[j] > p) { k = j; p = realEigenvalues[j]; } } if (k != i) { realEigenvalues[k] = realEigenvalues[i]; realEigenvalues[i] = p; for (int j = 0; j < n; j++) { p = z[j][i]; z[j][i] = z[j][k]; z[j][k] = p; } } } // Determine the largest eigen value in absolute term. maxAbsoluteValue = 0; for (int i = 0; i < n; i++) { if (FastMath.abs(realEigenvalues[i]) > maxAbsoluteValue) { maxAbsoluteValue = FastMath.abs(realEigenvalues[i]); } } // Make null any eigen value too small to be significant if (maxAbsoluteValue != 0.0) { for (int i = 0; i < n; i++) { if (FastMath.abs(realEigenvalues[i]) < Precision.EPSILON * maxAbsoluteValue) { realEigenvalues[i] = 0; } } } eigenvectors = new ArrayRealVector[n]; double[] tmp = new double[n]; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { tmp[j] = z[j][i]; } eigenvectors[i] = new ArrayRealVector(tmp); } }