/// <summary> /// Adds a scaled vector to another: <c>result = y + alpha*x</c>. /// </summary> /// <param name="y">The vector to update.</param> /// <param name="alpha">The value to scale <paramref name="x"/> by.</param> /// <param name="x">The vector to add to <paramref name="y"/>.</param> /// <param name="result">The result of the addition.</param> /// <remarks>This is similar to the AXPY BLAS routine.</remarks> public virtual void AddVectorToScaledVector(Complex32[] y, Complex32 alpha, Complex32[] x, Complex32[] result) { if (y == null) { throw new ArgumentNullException("y"); } if (x == null) { throw new ArgumentNullException("x"); } if (y.Length != x.Length) { throw new ArgumentException(Resources.ArgumentVectorsSameLength); } if (alpha.IsZero()) { CommonParallel.For(0, y.Length, index => result[index] = y[index]); } else if (alpha.IsOne()) { CommonParallel.For(0, y.Length, index => result[index] = y[index] + x[index]); } else { CommonParallel.For(0, y.Length, index => result[index] = y[index] + (alpha * x[index])); } }
/// <summary> /// Multiplies each element of the matrix by a scalar and places results into the result matrix. /// </summary> /// <param name="scalar">The scalar to multiply the matrix with.</param> /// <param name="result">The matrix to store the result of the multiplication.</param> protected override void DoMultiply(Complex32 scalar, Matrix <Complex32> result) { if (scalar.IsZero()) { result.Clear(); return; } if (scalar.IsOne()) { CopyTo(result); return; } var diagResult = result as DiagonalMatrix; if (diagResult == null) { base.DoMultiply(scalar, result); } else { Control.LinearAlgebraProvider.ScaleArray(scalar, _data, diagResult._data); } }
/// <summary> /// Adds a scaled vector to another: <c>result = y + alpha*x</c>. /// </summary> /// <param name="y">The vector to update.</param> /// <param name="alpha">The value to scale <paramref name="x"/> by.</param> /// <param name="x">The vector to add to <paramref name="y"/>.</param> /// <param name="result">The result of the addition.</param> /// <remarks>This is similar to the AXPY BLAS routine.</remarks> public virtual void AddVectorToScaledVector(Complex32[] y, Complex32 alpha, Complex32[] x, Complex32[] result) { if (y == null) { throw new ArgumentNullException("y"); } if (x == null) { throw new ArgumentNullException("x"); } if (y.Length != x.Length) { throw new ArgumentException(Resources.ArgumentVectorsSameLength); } if (alpha.IsZero()) { y.Copy(result); } else if (alpha.IsOne()) { if (Control.ParallelizeOperation(x.Length)) { CommonParallel.For(0, y.Length, index => result[index] = y[index] + x[index]); } else { for (var index = 0; index < x.Length; index++) { result[index] = y[index] + x[index]; } } } else { if (Control.ParallelizeOperation(x.Length)) { CommonParallel.For(0, y.Length, index => result[index] = y[index] + (alpha * x[index])); } else { for (var index = 0; index < x.Length; index++) { result[index] = y[index] + (alpha * x[index]); } } } }
//public override Complex32 Impedance(double W = 0) //{ // Complex32 Y = Complex32.Zero; // Complex32 Z2 = Complex32.Zero; // foreach (var item in Components) // { // Z2 = item.Impedance(W); // if (Z2.IsZero()) // return Complex32.PositiveInfinity; // Y += 1 / Z2; // } // return 1 / Y; //} public override Complex32 Impedance(Complex32?W = null) { Complex32 Y = Complex32.Zero; Complex32 Z2 = Complex32.Zero; foreach (var item in Components) { Z2 = item.Impedance(W); if (Z2.IsZero()) { return(Complex32.PositiveInfinity); } Y += 1 / Z2; } return(1 / Y); }
/// <summary> /// Adds a scaled vector to another: <c>result = y + alpha*x</c>. /// </summary> /// <param name="y">The vector to update.</param> /// <param name="alpha">The value to scale <paramref name="x"/> by.</param> /// <param name="x">The vector to add to <paramref name="y"/>.</param> /// <param name="result">The result of the addition.</param> /// <remarks>This is similar to the AXPY BLAS routine.</remarks> public virtual void AddVectorToScaledVector(Complex32[] y, Complex32 alpha, Complex32[] x, Complex32[] result) { if (y == null) { throw new ArgumentNullException("y"); } if (x == null) { throw new ArgumentNullException("x"); } if (y.Length != x.Length) { throw new ArgumentException(Resources.ArgumentVectorsSameLength); } if (alpha.IsZero()) { y.Copy(result); } else if (alpha.IsOne()) { CommonParallel.For(0, y.Length, 4096, (a, b) => { for (int i = a; i < b; i++) { result[i] = y[i] + x[i]; } }); } else { CommonParallel.For(0, y.Length, 4096, (a, b) => { for (int i = a; i < b; i++) { result[i] = y[i] + (alpha * x[i]); } }); } }
/// <summary> /// Adds a scaled vector to another: <c>y += alpha*x</c>. /// </summary> /// <param name="y">The vector to update.</param> /// <param name="alpha">The value to scale <paramref name="x"/> by.</param> /// <param name="x">The vector to add to <paramref name="y"/>.</param> /// <remarks>This equivalent to the AXPY BLAS routine.</remarks> public void AddVectorToScaledVector(Complex32[] y, Complex32 alpha, Complex32[] x) { if (y == null) { throw new ArgumentNullException("y"); } if (x == null) { throw new ArgumentNullException("x"); } if (y.Length != x.Length) { throw new ArgumentException(Resources.ArgumentVectorsSameLength); } if (alpha.IsZero()) { return; } SafeNativeMethods.c_axpy(y.Length, ref alpha, x, y); }
/// <summary> /// Multiplies each element of the matrix by a scalar and places results into the result matrix. /// </summary> /// <param name="scalar">The scalar to multiply the matrix with.</param> /// <param name="result">The matrix to store the result of the multiplication.</param> /// <exception cref="ArgumentNullException">If the result matrix is <see langword="null" />.</exception> /// <exception cref="ArgumentException">If the result matrix's dimensions are not the same as this matrix.</exception> protected override void DoMultiply(Complex32 scalar, Matrix<Complex32> result) { if (scalar.IsZero()) { result.Clear(); return; } if (scalar.IsOne()) { CopyTo(result); return; } var diagResult = result as DiagonalMatrix; if (diagResult == null) { base.Multiply(scalar, result); } else { if (!ReferenceEquals(this, result)) { CopyTo(diagResult); } Control.LinearAlgebraProvider.ScaleArray(scalar, Data, diagResult.Data); } }
public void CanDetermineIfZeroValueComplexNumber() { var complex = new Complex32(0, 0); Assert.IsTrue(complex.IsZero(), "Zero complex number."); }
/// <summary> /// Multiplies two matrices and updates another with the result. <c>c = alpha*op(a)*op(b) + beta*c</c> /// </summary> /// <param name="transposeA">How to transpose the <paramref name="a"/> matrix.</param> /// <param name="transposeB">How to transpose the <paramref name="b"/> matrix.</param> /// <param name="alpha">The value to scale <paramref name="a"/> matrix.</param> /// <param name="a">The a matrix.</param> /// <param name="rowsA">The number of rows in the <paramref name="a"/> matrix.</param> /// <param name="columnsA">The number of columns in the <paramref name="a"/> matrix.</param> /// <param name="b">The b matrix</param> /// <param name="rowsB">The number of rows in the <paramref name="b"/> matrix.</param> /// <param name="columnsB">The number of columns in the <paramref name="b"/> matrix.</param> /// <param name="beta">The value to scale the <paramref name="c"/> matrix.</param> /// <param name="c">The c matrix.</param> public void MatrixMultiplyWithUpdate(Transpose transposeA, Transpose transposeB, Complex32 alpha, Complex32[] a, int rowsA, int columnsA, Complex32[] b, int rowsB, int columnsB, Complex32 beta, Complex32[] c) { // Choose nonsensical values for the number of rows in c; fill them in depending // on the operations on a and b. int rowsC; // First check some basic requirement on the parameters of the matrix multiplication. if (a == null) { throw new ArgumentNullException("a"); } if (b == null) { throw new ArgumentNullException("b"); } if ((int)transposeA > 111 && (int)transposeB > 111) { if (rowsA != columnsB) { throw new ArgumentOutOfRangeException(); } if (columnsA * rowsB != c.Length) { throw new ArgumentOutOfRangeException(); } rowsC = columnsA; } else if ((int)transposeA > 111) { if (rowsA != rowsB) { throw new ArgumentOutOfRangeException(); } if (columnsA * columnsB != c.Length) { throw new ArgumentOutOfRangeException(); } rowsC = columnsA; } else if ((int)transposeB > 111) { if (columnsA != columnsB) { throw new ArgumentOutOfRangeException(); } if (rowsA * rowsB != c.Length) { throw new ArgumentOutOfRangeException(); } rowsC = rowsA; } else { if (columnsA != rowsB) { throw new ArgumentOutOfRangeException(); } if (rowsA * columnsB != c.Length) { throw new ArgumentOutOfRangeException(); } rowsC = rowsA; } if (alpha.IsZero() && beta.IsZero()) { Array.Clear(c, 0, c.Length); return; } // Check whether we will be overwriting any of our inputs and make copies if necessary. // TODO - we can don't have to allocate a completely new matrix when x or y point to the same memory // as result, we can do it on a row wise basis. We should investigate this. Complex32[] adata; if (ReferenceEquals(a, c)) { adata = (Complex32[])a.Clone(); } else { adata = a; } Complex32[] bdata; if (ReferenceEquals(b, c)) { bdata = (Complex32[])b.Clone(); } else { bdata = b; } if (alpha.IsOne()) { if (beta.IsZero()) { if ((int)transposeA > 111 && (int)transposeB > 111) { CommonParallel.For( 0, columnsA, j => { var jIndex = j * rowsC; for (var i = 0; i != rowsB; i++) { var iIndex = i * rowsA; Complex32 s = 0; for (var l = 0; l != columnsB; l++) { s += adata[iIndex + l] * bdata[(l * rowsB) + j]; } c[jIndex + i] = s; } }); } else if ((int)transposeA > 111) { CommonParallel.For( 0, columnsB, j => { var jcIndex = j * rowsC; var jbIndex = j * rowsB; for (var i = 0; i != columnsA; i++) { var iIndex = i * rowsA; Complex32 s = 0; for (var l = 0; l != rowsA; l++) { s += adata[iIndex + l] * bdata[jbIndex + l]; } c[jcIndex + i] = s; } }); } else if ((int)transposeB > 111) { CommonParallel.For( 0, rowsB, j => { var jIndex = j * rowsC; for (var i = 0; i != rowsA; i++) { Complex32 s = 0; for (var l = 0; l != columnsA; l++) { s += adata[(l * rowsA) + i] * bdata[(l * rowsB) + j]; } c[jIndex + i] = s; } }); } else { CommonParallel.For( 0, columnsB, j => { var jcIndex = j * rowsC; var jbIndex = j * rowsB; for (var i = 0; i != rowsA; i++) { Complex32 s = 0; for (var l = 0; l != columnsA; l++) { s += adata[(l * rowsA) + i] * bdata[jbIndex + l]; } c[jcIndex + i] = s; } }); } } else { if ((int)transposeA > 111 && (int)transposeB > 111) { CommonParallel.For( 0, columnsA, j => { var jIndex = j * rowsC; for (var i = 0; i != rowsB; i++) { var iIndex = i * rowsA; Complex32 s = 0; for (var l = 0; l != columnsB; l++) { s += adata[iIndex + l] * bdata[(l * rowsB) + j]; } c[jIndex + i] = (c[jIndex + i] * beta) + s; } }); } else if ((int)transposeA > 111) { CommonParallel.For( 0, columnsB, j => { var jcIndex = j * rowsC; var jbIndex = j * rowsB; for (var i = 0; i != columnsA; i++) { var iIndex = i * rowsA; Complex32 s = 0; for (var l = 0; l != rowsA; l++) { s += adata[iIndex + l] * bdata[jbIndex + l]; } c[jcIndex + i] = s + (c[jcIndex + i] * beta); } }); } else if ((int)transposeB > 111) { CommonParallel.For( 0, rowsB, j => { var jIndex = j * rowsC; for (var i = 0; i != rowsA; i++) { Complex32 s = 0; for (var l = 0; l != columnsA; l++) { s += adata[(l * rowsA) + i] * bdata[(l * rowsB) + j]; } c[jIndex + i] = s + (c[jIndex + i] * beta); } }); } else { CommonParallel.For( 0, columnsB, j => { var jcIndex = j * rowsC; var jbIndex = j * rowsB; for (var i = 0; i != rowsA; i++) { Complex32 s = 0; for (var l = 0; l != columnsA; l++) { s += adata[(l * rowsA) + i] * bdata[jbIndex + l]; } c[jcIndex + i] = s + (c[jcIndex + i] * beta); } }); } } } else { if ((int)transposeA > 111 && (int)transposeB > 111) { CommonParallel.For( 0, columnsA, j => { var jIndex = j * rowsC; for (var i = 0; i != rowsB; i++) { var iIndex = i * rowsA; Complex32 s = 0; for (var l = 0; l != columnsB; l++) { s += adata[iIndex + l] * bdata[(l * rowsB) + j]; } c[jIndex + i] = (c[jIndex + i] * beta) + (alpha * s); } }); } else if ((int)transposeA > 111) { CommonParallel.For( 0, columnsB, j => { var jcIndex = j * rowsC; var jbIndex = j * rowsB; for (var i = 0; i != columnsA; i++) { var iIndex = i * rowsA; Complex32 s = 0; for (var l = 0; l != rowsA; l++) { s += adata[iIndex + l] * bdata[jbIndex + l]; } c[jcIndex + i] = (alpha * s) + (c[jcIndex + i] * beta); } }); } else if ((int)transposeB > 111) { CommonParallel.For( 0, rowsB, j => { var jIndex = j * rowsC; for (var i = 0; i != rowsA; i++) { Complex32 s = 0; for (var l = 0; l != columnsA; l++) { s += adata[(l * rowsA) + i] * bdata[(l * rowsB) + j]; } c[jIndex + i] = (alpha * s) + (c[jIndex + i] * beta); } }); } else { CommonParallel.For( 0, columnsB, j => { var jcIndex = j * rowsC; var jbIndex = j * rowsB; for (var i = 0; i != rowsA; i++) { Complex32 s = 0; for (var l = 0; l != columnsA; l++) { s += adata[(l * rowsA) + i] * bdata[jbIndex + l]; } c[jcIndex + i] = (alpha * s) + (c[jcIndex + i] * beta); } }); } } }
/// <summary> /// Multiplies two matrices and updates another with the result. <c>c = alpha*op(a)*op(b) + beta*c</c> /// </summary> /// <param name="transposeA">How to transpose the <paramref name="a"/> matrix.</param> /// <param name="transposeB">How to transpose the <paramref name="b"/> matrix.</param> /// <param name="alpha">The value to scale <paramref name="a"/> matrix.</param> /// <param name="a">The a matrix.</param> /// <param name="rowsA">The number of rows in the <paramref name="a"/> matrix.</param> /// <param name="columnsA">The number of columns in the <paramref name="a"/> matrix.</param> /// <param name="b">The b matrix</param> /// <param name="rowsB">The number of rows in the <paramref name="b"/> matrix.</param> /// <param name="columnsB">The number of columns in the <paramref name="b"/> matrix.</param> /// <param name="beta">The value to scale the <paramref name="c"/> matrix.</param> /// <param name="c">The c matrix.</param> public virtual void MatrixMultiplyWithUpdate(Transpose transposeA, Transpose transposeB, Complex32 alpha, Complex32[] a, int rowsA, int columnsA, Complex32[] b, int rowsB, int columnsB, Complex32 beta, Complex32[] c) { int m; // The number of rows of matrix op(A) and of the matrix C. int n; // The number of columns of matrix op(B) and of the matrix C. int k; // The number of columns of matrix op(A) and the rows of the matrix op(B). // First check some basic requirement on the parameters of the matrix multiplication. if (a == null) { throw new ArgumentNullException("a"); } if (b == null) { throw new ArgumentNullException("b"); } if ((int)transposeA > 111 && (int)transposeB > 111) { if (rowsA != columnsB) { throw new ArgumentOutOfRangeException(); } if (columnsA * rowsB != c.Length) { throw new ArgumentOutOfRangeException(); } m = columnsA; n = rowsB; k = rowsA; } else if ((int)transposeA > 111) { if (rowsA != rowsB) { throw new ArgumentOutOfRangeException(); } if (columnsA * columnsB != c.Length) { throw new ArgumentOutOfRangeException(); } m = columnsA; n = columnsB; k = rowsA; } else if ((int)transposeB > 111) { if (columnsA != columnsB) { throw new ArgumentOutOfRangeException(); } if (rowsA * rowsB != c.Length) { throw new ArgumentOutOfRangeException(); } m = rowsA; n = rowsB; k = columnsA; } else { if (columnsA != rowsB) { throw new ArgumentOutOfRangeException(); } if (rowsA * columnsB != c.Length) { throw new ArgumentOutOfRangeException(); } m = rowsA; n = columnsB; k = columnsA; } if (alpha.IsZero() && beta.IsZero()) { Array.Clear(c, 0, c.Length); return; } // Check whether we will be overwriting any of our inputs and make copies if necessary. // TODO - we can don't have to allocate a completely new matrix when x or y point to the same memory // as result, we can do it on a row wise basis. We should investigate this. Complex32[] adata; if (ReferenceEquals(a, c)) { adata = (Complex32[])a.Clone(); } else { adata = a; } Complex32[] bdata; if (ReferenceEquals(b, c)) { bdata = (Complex32[])b.Clone(); } else { bdata = b; } if (beta.IsZero()) { Array.Clear(c, 0, c.Length); } else if (!beta.IsOne()) { Control.LinearAlgebraProvider.ScaleArray(beta, c, c); } if (alpha.IsZero()) { return; } CacheObliviousMatrixMultiply(transposeA, transposeB, alpha, adata, 0, 0, bdata, 0, 0, c, 0, 0, m, n, k, m, n, k, true); }
/// <summary> /// Scales an array. Can be used to scale a vector and a matrix. /// </summary> /// <param name="alpha">The scalar.</param> /// <param name="x">The values to scale.</param> /// <param name="result">This result of the scaling.</param> /// <remarks>This is similar to the SCAL BLAS routine.</remarks> public virtual void ScaleArray(Complex32 alpha, Complex32[] x, Complex32[] result) { if (x == null) { throw new ArgumentNullException("x"); } if (alpha.IsZero()) { CommonParallel.For(0, x.Length, index => result[index] = Complex32.Zero); } else if (alpha.IsOne()) { CommonParallel.For(0, x.Length, index => result[index] = x[index]); } else { CommonParallel.For(0, x.Length, index => { result[index] = alpha * x[index]; }); } }
/// <summary> /// Scales an array. Can be used to scale a vector and a matrix. /// </summary> /// <param name="alpha">The scalar.</param> /// <param name="x">The values to scale.</param> /// <param name="result">This result of the scaling.</param> /// <remarks>This is similar to the SCAL BLAS routine.</remarks> public virtual void ScaleArray(Complex32 alpha, Complex32[] x, Complex32[] result) { if (x == null) { throw new ArgumentNullException("x"); } if (alpha.IsZero()) { Array.Clear(result, 0, result.Length); } else if (alpha.IsOne()) { x.Copy(result); } else { if (Control.ParallelizeOperation(x.Length)) { CommonParallel.For(0, x.Length, 4096, (a, b) => { for (int i = a; i < b; i++) { result[i] = alpha*x[i]; } }); } else { for (var index = 0; index < x.Length; index++) { result[index] = alpha*x[index]; } } } }
/// <summary> /// Initializes a new instance of the <see cref="SparseMatrix"/> class with all entries set to a particular value. /// </summary> /// <param name="rows"> /// The number of rows. /// </param> /// <param name="columns"> /// The number of columns. /// </param> /// <param name="value">The value which we assign to each element of the matrix.</param> public SparseMatrix(int rows, int columns, Complex32 value) : this(rows, columns) { if (value.IsZero()) { return; } var rowPointers = _storage.RowPointers; var valueCount = _storage.ValueCount = rows * columns; var columnIndices = _storage.ColumnIndices = new int[valueCount]; var values = _storage.Values = new Complex32[valueCount]; for (int i = 0, j = 0; i < values.Length; i++, j++) { // Reset column position to "0" if (j == columns) { j = 0; } values[i] = value; columnIndices[i] = j; } // Set proper row pointers for (var i = 0; i < rowPointers.Length; i++) { rowPointers[i] = ((i + 1) * columns) - columns; } }