/*---------------------------------------------------------------------------------------------------------------------- | 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; }
/*---------------------------------------------------------------------------------------------------------------------- | 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; }
/*---------------------------------------------------------------------------------------------------------------------- | 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; }
/*---------------------------------------------------------------------------------------------------------------------- | 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; }
/*---------------------------------------------------------------------------------------------------------------------- | 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; }
/*---------------------------------------------------------------------------------------------------------------------- | 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; }