public static Vector operator -(Vector vector, double val) { EnsureValid(vector); var v = new Vector(vector.NRows); Parallel.For(0, v.NRows, i => v[i] = vector[i] - val); return v; }
public static Vector operator +(Vector target, Vector source) { EnsureValid(source, "Source vector"); EnsureValid(target, "Target vector"); EnsureCompatible(target, source); var v = new Vector(target.NRows); Parallel.For(0, v.NRows, i => v[i] = target[i] + source[i]); return v; }
public static bool AreCompatible(Vector v1, Vector v2) { EnsureValid(v1, "Vector 1"); EnsureValid(v2, "Vector 2"); return v1.NRows == v2.NRows; }
private static void EnsureValid(Vector v, string name = "Vector") { if (!v.IsValid()) throw new ArgumentException($"{name} is not initialized"); }
private static void EnsureCompatible(Vector v1, Vector v2) { if (!AreCompatible(v1, v2)) throw new ArgumentException("Vectors are not compatible"); }
public Vector Sqrt() { EnsureValid(this); var v = new Vector(NRows); Parallel.For(0, NRows, i => v[i] = Math.Sqrt(this.Elements[i])); return v; }
public Vector ElementDiv(Vector target, Vector source) { EnsureValid(source, "Source vector"); EnsureValid(target, "Target vector"); EnsureCompatible(target, source); var v = new Vector(target.NRows); Parallel.For(0, NRows, i => v[i] = target[i] / source[i]); return v; }
public Vector Sqr() { EnsureValid(this); var v = new Vector(NRows); Parallel.For(0, this.NRows, i => v[i] = this.Elements[i] * this.Elements[i]); return v; }
public void MakeTridiagonal(Matrix a, Vector d, Vector e) { int num1 = a.m; if (a.m != a.n) throw new ArgumentException("Matrix to tridiagonalize must be square"); if (!a.IsSymmetric) throw new ArgumentException("Can only tridiagonalise symmetric matrix"); var numArray1 = new double[this.M * this.N]; for (int index = 0; index < this.M * this.N; ++index) numArray1[index] = a.Elements[index / this.M, index % this.N]; var elements1 = d.Elements; var elements2 = e.Elements; for (int index1 = num1 - 1; index1 > 0; --index1) { int num2 = index1 - 1; double d1 = 0.0; double num3 = 0.0; if (num2 > 0) { for (int index2 = 0; index2 <= num2; ++index2) num3 += Math.Abs(numArray1[index1 + index2 * num1]); if (num3 == 0.0) { elements2[index1] = numArray1[index1 + num2 * num1]; } else { for (int index2 = 0; index2 <= num2; ++index2) { numArray1[index1 + index2 * num1] /= num3; d1 += numArray1[index1 + index2 * num1] * numArray1[index1 + index2 * num1]; } double num4 = numArray1[index1 + num2 * num1]; double num5 = num4 < 0.0 ? Math.Sqrt(d1) : -Math.Sqrt(d1); elements2[index1] = num3 * num5; d1 -= num4 * num5; numArray1[index1 + num2 * num1] = num4 - num5; double num6 = 0.0; for (int index2 = 0; index2 <= num2; ++index2) { numArray1[index2 + index1 * num1] = numArray1[index1 + index2 * num1] / d1; double num7 = 0.0; for (int index3 = 0; index3 <= index2; ++index3) num7 += numArray1[index2 + index3 * num1] * numArray1[index1 + index3 * num1]; for (int index3 = index2 + 1; index3 <= num2; ++index3) num7 += numArray1[index3 + index2 * num1] * numArray1[index1 + index3 * num1]; elements2[index2] = num7 / d1; num6 += elements2[index2] * numArray1[index1 + index2 * num1]; } double num8 = num6 / (d1 + d1); for (int index2 = 0; index2 <= num2; ++index2) { double num7 = numArray1[index1 + index2 * num1]; double num9; elements2[index2] = num9 = elements2[index2] - num8 * num7; for (int index3 = 0; index3 <= index2; ++index3) numArray1[index2 + index3 * num1] -= num7 * elements2[index3] + num9 * numArray1[index1 + index3 * num1]; } } } else elements2[index1] = numArray1[index1 + num2 * num1]; elements1[index1] = d1; } elements1[0] = 0.0; elements2[0] = 0.0; for (int index1 = 0; index1 < num1; ++index1) { int num2 = index1 - 1; if (elements1[index1] != 0.0) { for (int index2 = 0; index2 <= num2; ++index2) { double num3 = 0.0; for (int index3 = 0; index3 <= num2; ++index3) num3 += numArray1[index1 + index3 * num1] * numArray1[index3 + index2 * num1]; for (int index3 = 0; index3 <= num2; ++index3) numArray1[index3 + index2 * num1] -= num3 * numArray1[index3 + index1 * num1]; } } elements1[index1] = numArray1[index1 + index1 * num1]; numArray1[index1 + index1 * num1] = 1.0; for (int index2 = 0; index2 <= num2; ++index2) { double[] numArray2 = numArray1; int index3 = index2 + index1 * num1; double[] numArray3 = numArray1; int index4 = index1 + index2 * num1; double num3 = 0.0; double num4 = 0.0; numArray3[index4] = num3; double num5 = num4; numArray2[index3] = num5; } } for (int index = 0; index < this.M * this.N; ++index) a.Elements[index / this.M, index % this.N] = numArray1[index]; }
public Matrix EigenVectors(Vector eigenValues) { if (!this.IsSymmetric) throw new NotImplementedException("Not yet implemented for non-symmetric matrix"); var matrix = new Matrix(this.Rows, this.Cols); for (int index1 = 0; index1 < this.Rows; ++index1) for (int index2 = 0; index2 < this.Cols; ++index2) matrix[index1, index2] = this[index1, index2]; eigenValues.ResizeTo(this.Rows); var e = new Vector(this.Rows); MakeTridiagonal(matrix, eigenValues, e); MakeEigenVectors(eigenValues, e, matrix); EigenSort(matrix, eigenValues); return matrix; }
public void EigenSort(Matrix eigenVectors, Vector eigenValues) { int rows = eigenVectors.Rows; double[] numArray = new double[rows * rows]; for (int index = 0; index < rows * rows; ++index) numArray[index] = eigenVectors.Elements[index / rows, index % rows]; double[] elements = eigenValues.Elements; for (int index1 = 0; index1 < rows; ++index1) { int index2 = index1; double num1 = elements[index1]; for (int index3 = index1 + 1; index3 < rows; ++index3) { if (elements[index3] >= num1) { index2 = index3; num1 = elements[index3]; } } if (index2 != index1) { elements[index2] = elements[index1]; elements[index1] = num1; for (int index3 = 0; index3 < rows; ++index3) { double num2 = numArray[index3 + index1 * rows]; numArray[index3 + index1 * rows] = numArray[index3 + index2 * rows]; numArray[index3 + index2 * rows] = num2; } } } for (int index = 0; index < rows * rows; ++index) eigenVectors.Elements[index / rows, index % rows] = numArray[index]; }
public void MakeEigenVectors(Vector d, Vector e, Matrix z) { int rows = z.Rows; double[] elements1 = d.Elements; double[] elements2 = e.Elements; double[] numArray = new double[rows * rows]; for (int index = 0; index < rows * rows; ++index) numArray[index] = z.Elements[index / rows, index % rows]; for (int index = 1; index < rows; ++index) elements2[index - 1] = elements2[index]; elements2[rows - 1] = 0.0; for (int index1 = 0; index1 < rows; ++index1) { int num1 = 0; int index2; do { for (index2 = index1; index2 < rows - 1; ++index2) { double num2 = Math.Abs(elements1[index2]) + Math.Abs(elements1[index2 + 1]); if (Math.Abs(elements2[index2]) + num2 == num2) break; } if (index2 != index1) { if (num1++ != 30) { double num2 = (elements1[index1 + 1] - elements1[index1]) / (2.0 * elements2[index1]); double num3 = Math.Sqrt(num2 * num2 + 1.0); double num4 = elements1[index2] - elements1[index1] + elements2[index1] / (num2 + (num2 >= 0.0 ? Math.Abs(num3) : -Math.Abs(num3))); double num5 = 1.0; double num6 = 1.0; double num7 = 0.0; int index3; for (index3 = index2 - 1; index3 >= index1; --index3) { double num8 = num5 * elements2[index3]; double num9 = num6 * elements2[index3]; num3 = Math.Sqrt(num8 * num8 + num4 * num4); elements2[index3 + 1] = num3; if (num3 != 0.0) { num5 = num8 / num3; num6 = num4 / num3; double num10 = elements1[index3 + 1] - num7; num3 = (elements1[index3] - num10) * num5 + 2.0 * num6 * num9; num7 = num5 * num3; elements1[index3 + 1] = num10 + num7; num4 = num6 * num3 - num9; for (int index4 = 0; index4 < rows; ++index4) { double num11 = numArray[index4 + (index3 + 1) * rows]; numArray[index4 + (index3 + 1) * rows] = num5 * numArray[index4 + index3 * rows] + num6 * num11; numArray[index4 + index3 * rows] = num6 * numArray[index4 + index3 * rows] - num5 * num11; } } else { elements1[index3 + 1] -= num7; elements2[index2] = 0.0; break; } } if (num3 != 0.0 || index3 < index1) { elements1[index1] -= num7; elements2[index1] = num4; elements2[index2] = 0.0; } } else goto label_31; } } while (index2 != index1); continue; label_31: Error("MakeEigenVectors", "too many iterationsn"); return; } for (int index = 0; index < rows * rows; ++index) z.Elements[index / rows, index % rows] = numArray[index]; }