Пример #1
0
        /// <summary>
        /// Generates diagonal matrix
        /// </summary>
        /// <param name="diag_vector">column vector containing the diag elements</param>
        /// <returns></returns>
        public static ArrayMatrix Diag(ArrayMatrix diag_vector, int offset)
        {
            var dim = diag_vector.VectorLength();

            if (dim == 0) throw new ArgumentException("diag_vector must be 1xN or Nx1.");

            //if (Math.Abs(offset) >= dim)
            //    throw new ArgumentException("Absolute value of offset must be less than length of diag_vector.");

            var M = new ArrayMatrix(dim + Math.Abs(offset), dim + Math.Abs(offset));
            dim = M.RowCount;

            if (offset >= 0) for (var i = 1; i <= dim - offset; i++) M[i, i + offset] = diag_vector[i];
            else for (var i = 1; i <= dim + offset; i++) M[i - offset, i] = diag_vector[i];

            return M;
        }
Пример #2
0
        /// <summary>
        /// Implements the dot product of two vectors.
        /// </summary>
        /// <param name="v">Row or column vector.</param>
        /// <param name="w">Row or column vector.</param>
        /// <returns>Dot product.</returns>
        public static Complex Dot(ArrayMatrix v, ArrayMatrix w)
        {
            var m = v.VectorLength();
            var n = w.VectorLength();

            if (m == 0 || n == 0) throw new ArgumentException("Arguments need to be vectors.");
            else if (m != n) throw new ArgumentException("Vectors must be of the same length.");

            var buf = Complex.Zero;

            for (var i = 1; i <= m; i++) buf += v[i]*w[i];

            return buf;
        }
Пример #3
0
        /// <summary>
        /// Computes the Householder vector.
        /// </summary>
        /// <param name="x"></param>
        /// <returns></returns>
        static ArrayMatrix[] HouseholderVector(ArrayMatrix x)
        {
            //throw new NotImplementedException("Supposingly buggy!");

            //if (!x.IsReal())
            //    throw new ArgumentException("Cannot compute housholder vector of non-real vector.");

            var n = x.VectorLength();

            if (n == 0) throw new InvalidOperationException("Expected vector as argument.");

            var y = x/x.Norm();
            var buf = y.Extract(2, n, 1, 1);
            var s = Dot(buf, buf);

            var v = Zeros(n, 1);
            v[1] = Complex.One;

            v.Insert(2, 1, buf);

            double beta = 0;

            if (s != 0)
            {
                var mu = Complex.Sqrt(y[1]*y[1] + s);
                if (y[1].Real <= 0) v[1] = y[1] - mu;
                else v[1] = -s/(y[1] + mu);

                beta = 2*v[1].Real*v[1].Real/(s.Real + v[1].Real*v[1].Real);
                v = v/v[1];
            }

            return new ArrayMatrix[] {v, new ArrayMatrix(beta)};
        }
Пример #4
0
        /// <summary>
        /// Generates diagonal matrix
        /// </summary>
        /// <param name="diag_vector">column vector containing the diag elements</param>
        /// <returns></returns>
        public static ArrayMatrix Diag(ArrayMatrix diag_vector)
        {
            var dim = diag_vector.VectorLength();

            if (dim == 0) throw new ArgumentException("diag_vector must be 1xN or Nx1");

            var M = new ArrayMatrix(dim, dim);

            for (var i = 1; i <= dim; i++) M[i, i] = diag_vector[i];

            return M;
        }
Пример #5
0
        /// <summary>
        /// Inserts row at specified index.
        /// </summary>
        /// <param name="row">Vector to insert</param>
        /// <param name="i">One-based index at which to insert</param>
        public void InsertRow(ArrayMatrix row, int i)
        {
            var size = row.VectorLength();

            if (size == 0) throw new InvalidOperationException("Row must be a vector of length > 0.");

            if (i <= 0) throw new ArgumentException("Row index must be positive.");

            if (i > RowCount) this[i, size] = Complex.Zero;

            else if (size > ColumnCount)
            {
                this[i, size] = Complex.Zero;
                RowCount++;
            }
            else RowCount++;

            Values.Insert(--i, new ArrayList(size));
            //Debug.WriteLine(Values.Count.ToString());

            for (var k = 1; k <= size; k++) ((ArrayList) Values[i]).Add(row[k]);

            // fill w/ zeros if vector row is too short
            for (var k = size; k < ColumnCount; k++) ((ArrayList) Values[i]).Add(Complex.Zero);
        }
Пример #6
0
        /// <summary>
        /// Inserts column at specified index.
        /// </summary>
        /// <param name="col">Vector to insert</param>
        /// <param name="j">One-based index at which to insert</param>
        public void InsertColumn(ArrayMatrix col, int j)
        {
            var size = col.VectorLength();

            if (size == 0) throw new InvalidOperationException("Row must be a vector of length > 0.");

            if (j <= 0) throw new ArgumentException("Row index must be positive.");

            if (j > ColumnCount) this[size, j] = Complex.Zero;
            else ColumnCount++;

            if (size > RowCount) this[size, j] = Complex.Zero;

            j--;

            for (var k = 0; k < size; k++) ((ArrayList) Values[k]).Insert(j, col[k + 1]);

            // fill w/ zeros if vector col too short
            for (var k = size; k < RowCount; k++) ((ArrayList) Values[k]).Insert(j, 0);
        }
Пример #7
0
        /// <summary>
        /// Performs forward insertion for regular lower triangular matrix
        /// and right side b, such that the solution is saved right within b.
        /// The matrix is not changed.
        /// </summary>
        /// <param name="b">Vector of height n, if matrix is n by n.</param>
        public void ForwardInsertion(ArrayMatrix b)
        {
            if (!IsLowerTriangular()) throw new InvalidOperationException("Cannot perform forward insertion for matrix not being lower triangular.");

            if ( /*this.Determinant*/DiagProd() == 0) throw new InvalidOperationException("Warning: Matrix is nearly singular.");

            var n = RowCount;

            if (b.VectorLength() != n) throw new ArgumentException("Parameter must vector of the same height as matrix.");

            for (var j = 1; j <= n - 1; j++)
            {
                b[j] /= this[j, j];

                for (var i = 1; i <= n - j; i++) b[j + i] -= b[j]*this[j + i, j];
            }

            b[n] /= this[n, n];
        }
Пример #8
0
        /// <summary>
        /// Performs backward insertion for regular upper triangular matrix
        /// and right side b, such that the solution is saved right within b.
        /// The matrix is not changed.
        /// </summary>
        /// <param name="b">Vector of height n, if matrix is n by n.</param>
        public void BackwardInsertion(ArrayMatrix b)
        {
            if (!IsUpperTriangular())
                throw new InvalidOperationException(
                    "Cannot perform backward insertion for matrix not being upper triangular.");

            if ( /*this.Determinant*/DiagProd() == 0) throw new InvalidOperationException("Warning: Matrix is nearly singular.");

            var n = RowCount;

            if (b.VectorLength() != n) throw new ArgumentException("Parameter must vector of the same height as matrix.");

            for (var j = n; j >= 2; j--)
            {
                b[j] /= this[j, j];

                for (var i = 1; i <= j - 1; i++) b[i] -= b[j]*this[i, j];
            }

            b[1] /= this[1, 1];
        }
Пример #9
0
        /// <summary>
        /// Generates tri-diagonal square matrix with overloaded vectors
        /// as main and secondary diagonals. The dimension of the output
        /// matrix is determined by the length of d.
        /// </summary>
        /// <param name="l">Lower secondary diagonal vector.</param>
        /// <param name="d">Main diagonal vector.</param>
        /// <param name="u">Upper secondary diagonal vector.</param>
        /// <returns></returns>
        public static ArrayMatrix TriDiag(ArrayMatrix l, ArrayMatrix d, ArrayMatrix u)
        {
            var sizeL = l.VectorLength();
            var sizeD = d.VectorLength();
            var sizeU = u.VectorLength();

            if (sizeL*sizeD*sizeU == 0) throw new ArgumentException("At least one of the paramter matrices is not a vector.");

            if (sizeL != sizeU) throw new ArgumentException("Lower and upper secondary diagonal must have the same length.");

            if (sizeL + 1 != sizeD) throw new ArgumentException("Main diagonal must have exactly one element more than the secondary diagonals.");

            return Diag(l, -1) + Diag(d) + Diag(u, 1);
        }