示例#1
0
/*----------------------------------------------------------------------------------------------------------------------
|	Creates and returns a matrix that represents the inverse of this SquareMatrix.
*/
SquareMatrix * SquareMatrix::Inverse() const
    {
    double * col = new double[dim];
    int * permutation = new int[dim];
    SquareMatrix * tmp = new SquareMatrix(*this);
    double ** a = tmp->GetMatrixAsRawPointer();
    SquareMatrix * inv = new SquareMatrix(*this);
    double ** a_inv = inv->GetMatrixAsRawPointer();

    // double **  a           matrix represented as vector of row pointers
    // int        n           order of matrix
    // double *   col         work vector of size n
    // int *      permutation work vector of size n
    // double **  a_inv       inverse of input matrix a (matrix a is destroyed)
    int result = InvertMatrix(a, dim, col, permutation, a_inv);
    delete tmp;
    delete [] col;
    delete [] permutation;
    if (result != 0)
        {
        delete inv;
        return 0;
        }
    return inv;
    }
示例#2
0
/*----------------------------------------------------------------------------------------------------------------------
|	Creates and returns a matrix that represents this matrix raised to the power `p'.
*/
SquareMatrix * SquareMatrix::Power(
  double p) const   /**< the power to which this matrix should be raised */
    {
	PHYCAS_ASSERT(dim > 0);
	//PHYCAS_ASSERT(p > 0.0);
    double * fv = new double[dim];
    double * w = new double[dim];
    double ** a = this->GetMatrixAsRawPointer();
    SquareMatrix * Z = new SquareMatrix(dim, 0.0);
    double ** z = Z->GetMatrixAsRawPointer();

	// Calculate eigenvalues (w) and eigenvectors (z)
    // int n        input: the order of the matrix a
    // double **a   input: the real symmetric matrix
    // double *fv   input: temporary storage array of at least n elements
    // double **z   output: the eigenvectors
    // double *w    output: the eigenvalues in ascending order
	int err_code = EigenRealSymmetric(dim, a, w, z, fv);
    if (err_code != 0)
        {
        delete Z;
        delete [] fv;
        delete [] w;
        return 0;
        }

    SquareMatrix * Zinv = Z->Inverse();
    SquareMatrix * Lp = new SquareMatrix(dim, 0.0);

    // create diagonal matrix of scaled eigenvalues
    for (unsigned i = 0; i < dim; ++i)
        {
        double v = pow(w[i],p);
        Lp->SetElement(i, i, v);
        }

    // Zinv * A * Z = L
    //            A = Z * L * Zinv
    //          A^p = Z * L^p * Zinv
    SquareMatrix * ZLp = Z->RightMultiplyMatrix(*Lp);
    SquareMatrix * Ap = ZLp->RightMultiplyMatrix(*Zinv);

    delete Z;
    delete Zinv;
    delete Lp;
    delete ZLp;
    delete [] fv;
    delete [] w;

    return Ap;
    }
示例#3
0
/*----------------------------------------------------------------------------------------------------------------------
|	Returns the Cholesky decomposition of this SquareMatrix as a lower-triangular matrix. Assumes this SquareMatrix is
|   symmetric and positive definite.
*/
SquareMatrix * SquareMatrix::CholeskyDecomposition() const
    {
	PHYCAS_ASSERT(dim > 0);
    SquareMatrix * L = new SquareMatrix(*this);
    double * p = new double[dim];
    double ** a = L->GetMatrixAsRawPointer();

    for (unsigned i = 0; i < dim; ++i)
        {
        for (unsigned j = i; j < dim; ++j)
            {
            double sum = a[i][j];
            for (int k = i-1; k >= 0; --k)
                {
                sum -= a[i][k]*a[j][k];
                }
            if (i == j)
                {
                if (sum <= 0.0)
                    {
                    // matrix is not positive definite
                    return 0;
                    }
                p[i] = sqrt(sum);
                }
            else
                {
                a[j][i] = sum/p[i];
                }
            }
        }

    // zero out upper diagonal and copy diagonal elements
    for (unsigned i = 0; i < dim; ++i)
        {
        a[i][i] = p[i];
        for (unsigned j = i+1; j < dim; ++j)
            {
            a[i][j] = 0.0;
            }
        }

    return L;
    }
示例#4
0
/*----------------------------------------------------------------------------------------------------------------------
|	Creates and returns a matrix that represents the product of this matrix with `matrixOnRight'.
*/
SquareMatrix * SquareMatrix::RightMultiplyMatrix(SquareMatrix & matrixOnRight) const
    {
    double ** l = GetMatrixAsRawPointer();
    double ** r = matrixOnRight.GetMatrixAsRawPointer();
    SquareMatrix * tmp = new SquareMatrix(*this);
    double ** t = tmp->GetMatrixAsRawPointer();

    for (unsigned i = 0; i < dim; ++i)
        {
        for (unsigned j = 0; j < dim; ++j)
            {
            double vsum = 0.0;
            for (unsigned k = 0; k < dim; ++k)
                {
                vsum += l[i][k]*r[k][j];
                }
            t[i][j] = vsum;
            }
        }
    return tmp;
    }
示例#5
0
/*----------------------------------------------------------------------------------------------------------------------
|	Returns the LU decomposition of this SquareMatrix.
*/
SquareMatrix * SquareMatrix::LUDecomposition() const
    {
	PHYCAS_ASSERT(dim > 0);
    SquareMatrix * L = new SquareMatrix(*this);
    double * scaling = new double[dim];
    int * permutation = new int[dim];
    double ** a = L->GetMatrixAsRawPointer();
	int err_code = LUDecompose(a, dim, scaling, permutation, NULL);
    if (err_code == 0)
        {
        // LUDecompose worked
        delete [] scaling;
        delete [] permutation;
        return L;
        }

    // Should throw an exception here
    delete L;
    delete [] scaling;
    delete [] permutation;
    return 0;
    }
示例#6
0
/*----------------------------------------------------------------------------------------------------------------------
|	Returns the natural logarithm of the product of the eigenvalues of this SquareMatrix.
*/
double SquareMatrix::LogDeterminant() const
    {
	PHYCAS_ASSERT(dim > 0);
    double * fv = new double[dim];
    double * w = new double[dim];
    double ** a = this->GetMatrixAsRawPointer();
    SquareMatrix * Z = new SquareMatrix(dim, 0.0);
    double ** z = Z->GetMatrixAsRawPointer();

	// Calculate eigenvalues (w) and eigenvectors (z)
    // int n        input: the order of the matrix a
    // double **a   input: the real symmetric matrix
    // double *fv   input: temporary storage array of at least n elements
    // double **z   output: the eigenvectors
    // double *w    output: the eigenvalues in ascending order
	int err_code = EigenRealSymmetric(dim, a, w, z, fv);
    if (err_code != 0)
        {
        delete Z;
        delete [] fv;
        delete [] w;
        return 0;
        }

    double log_det = 0.0;
    for (unsigned i = 0; i < dim; ++i)
        {
        double v = w[i];
        log_det += log(v);
        }

    delete Z;
    delete [] fv;
    delete [] w;

    return log_det;
    }