コード例 #1
0
ファイル: matrix_MxN.cpp プロジェクト: JianpingCAI/Physika
void MatrixMxN<Scalar>::singularValueDecomposition(MatrixMxN<Scalar> &left_singular_vectors,
                                                   VectorND<Scalar> &singular_values,
                                                   MatrixMxN<Scalar> &right_singular_vectors) const
{
#ifdef PHYSIKA_USE_EIGEN_MATRIX
    //hack: Eigen::SVD does not support integer types, hence we cast Scalar to long double for decomposition
    unsigned int rows = this->rows(), cols = this->cols();
    Eigen::Matrix<long double,Eigen::Dynamic,Eigen::Dynamic> temp_matrix(rows,cols);
    for(unsigned int i = 0; i < rows; ++i)
        for(unsigned int j = 0; j < cols; ++j)          
                temp_matrix(i,j) = static_cast<long double>((*ptr_eigen_matrix_MxN_)(i,j));
    Eigen::JacobiSVD<Eigen::Matrix<long double,Eigen::Dynamic,Eigen::Dynamic> > svd(temp_matrix,Eigen::ComputeThinU|Eigen::ComputeThinV);
    const Eigen::Matrix<long double,Eigen::Dynamic,Eigen::Dynamic> &left = svd.matrixU(), &right = svd.matrixV();
    const Eigen::Matrix<long double,Eigen::Dynamic,1> &values = svd.singularValues();
    //resize if have to
    if(left_singular_vectors.rows() != left.rows() || left_singular_vectors.cols() != left.cols())
        left_singular_vectors.resize(left.rows(),left.cols());
    if(right_singular_vectors.rows() != right.rows() || right_singular_vectors.cols() != right.cols())
        right_singular_vectors.resize(right.rows(),right.cols());
    if(singular_values.dims() != values.rows())
        singular_values.resize(values.rows());
    //copy the result
    for(unsigned int i = 0; i < left.rows(); ++i)
        for(unsigned int j = 0; j < left.cols(); ++j)
            left_singular_vectors(i,j) = static_cast<Scalar>(left(i,j));
    for(unsigned int i = 0; i < right.rows(); ++i)
        for(unsigned int j = 0; j < right.cols(); ++j)
            right_singular_vectors(i,j) = static_cast<Scalar>(right(i,j));
    for(unsigned int i = 0; i < values.rows(); ++i)
        singular_values[i] = static_cast<Scalar>(values(i,0));
#elif defined(PHYSIKA_USE_BUILT_IN_MATRIX)
    std::cerr<<"SVD not implemeted for built in matrix!\n";
    std::exit(EXIT_FAILURE);
#endif
}
コード例 #2
0
    void SetUp(const ::benchmark::State& state) {
        std::mt19937 rng{0};
        std::uniform_real_distribution<> d(0.0, 1.0);

        const auto n = static_cast<size_t>(state.range(0));

        mat.resize(n, n);
        x.resize(n);
        y.resize(n);
        mat.forEachIndex([&](size_t i, size_t j) { mat(i, j) = d(rng); });
        x.forEachIndex([&](size_t i) {
            x[i] = d(rng);
            y[i] = d(rng);
        });
    }
コード例 #3
0
void FdmJacobiSolver3::relax(const MatrixCsrD& A, const VectorND& b,
                             VectorND* x_, VectorND* xTemp_) {
    const auto rp = A.rowPointersBegin();
    const auto ci = A.columnIndicesBegin();
    const auto nnz = A.nonZeroBegin();

    VectorND& x = *x_;
    VectorND& xTemp = *xTemp_;

    b.parallelForEachIndex([&](size_t i) {
        const size_t rowBegin = rp[i];
        const size_t rowEnd = rp[i + 1];

        double r = 0.0;
        double diag = 1.0;
        for (size_t jj = rowBegin; jj < rowEnd; ++jj) {
            size_t j = ci[jj];

            if (i == j) {
                diag = nnz[jj];
            } else {
                r += nnz[jj] * x[j];
            }
        }

        xTemp[i] = (b[i] - r) / diag;
    });
}
コード例 #4
0
void FdmGaussSeidelSolver3::relax(const MatrixCsrD& A, const VectorND& b,
                                  double sorFactor, VectorND* x_) {
    const auto rp = A.rowPointersBegin();
    const auto ci = A.columnIndicesBegin();
    const auto nnz = A.nonZeroBegin();

    VectorND& x = *x_;

    b.forEachIndex([&](size_t i) {
        const size_t rowBegin = rp[i];
        const size_t rowEnd = rp[i + 1];

        double r = 0.0;
        double diag = 1.0;
        for (size_t jj = rowBegin; jj < rowEnd; ++jj) {
            size_t j = ci[jj];

            if (i == j) {
                diag = nnz[jj];
            } else {
                r += nnz[jj] * x[j];
            }
        }

        x[i] = (1.0 - sorFactor) * x[i] + sorFactor * (b[i] - r) / diag;
    });
}
コード例 #5
0
ファイル: vector_Nd.cpp プロジェクト: suitmyself/Physika
const MatrixMxN<Scalar> VectorND<Scalar>::outerProduct(const VectorND<Scalar> &vec2) const
{
    MatrixMxN<Scalar> result(this->dims(),vec2.dims());
    for(unsigned int i = 0; i < result.rows(); ++i)
        for(unsigned int j = 0; j < result.cols(); ++j)
            result(i,j) = (*this)[i]*vec2[j];
    return result;
}
コード例 #6
0
ファイル: matrix_MxN.cpp プロジェクト: JianpingCAI/Physika
void MatrixMxN<Scalar>::eigenDecomposition(VectorND<Scalar> &eigen_values_real, VectorND<Scalar> &eigen_values_imag,
                                           MatrixMxN<Scalar> &eigen_vectors_real, MatrixMxN<Scalar> &eigen_vectors_imag)
{
    unsigned int rows = this->rows(), cols = this->cols();
    if(rows != cols)
    {
        std::cerr<<"Eigen decomposition is only valid for square matrix!\n";
        std::exit(EXIT_FAILURE);
    }
#ifdef PHYSIKA_USE_EIGEN_MATRIX
    //hack: Eigen::EigenSolver does not support integer types, hence we cast Scalar to long double for decomposition
    Eigen::Matrix<long double,Eigen::Dynamic,Eigen::Dynamic> temp_matrix(rows,cols);
    for(unsigned int i = 0; i < rows; ++i)
        for(unsigned int j = 0; j < cols; ++j)          
                temp_matrix(i,j) = static_cast<long double>((*ptr_eigen_matrix_MxN_)(i,j));
    Eigen::EigenSolver<Eigen::Matrix<long double,Eigen::Dynamic,Eigen::Dynamic> > eigen(temp_matrix);
    Eigen::Matrix<std::complex<long double>,Eigen::Dynamic,Eigen::Dynamic> vectors = eigen.eigenvectors();
    const Eigen::Matrix<std::complex<long double>,Eigen::Dynamic,1> &values = eigen.eigenvalues();
    //resize if have to
    if(eigen_vectors_real.rows() != vectors.rows() || eigen_vectors_real.cols() != vectors.cols())
        eigen_vectors_real.resize(vectors.rows(),vectors.cols());
    if(eigen_vectors_imag.rows() != vectors.rows() || eigen_vectors_imag.cols() != vectors.cols())
        eigen_vectors_imag.resize(vectors.rows(),vectors.cols());
    if(eigen_values_real.dims() != values.rows())
        eigen_values_real.resize(values.rows());
    if(eigen_values_imag.dims() != values.rows())
        eigen_values_imag.resize(values.rows());
    //copy the result
    for(unsigned int i = 0; i < vectors.rows(); ++i)
        for(unsigned int j = 0; j < vectors.cols(); ++j)
        {
            eigen_vectors_real(i,j) = static_cast<Scalar>(vectors(i,j).real());
            eigen_vectors_imag(i,j) = static_cast<Scalar>(vectors(i,j).imag());
        }
    for(unsigned int i = 0; i < values.rows(); ++i)
    {
        eigen_values_real[i] = static_cast<Scalar>(values(i,0).real());
        eigen_values_imag[i] = static_cast<Scalar>(values(i,0).imag());
    }
#elif defined(PHYSIKA_USE_BUILT_IN_MATRIX)
    std::cerr<<"Eigen decomposition not implemeted for built in matrix!\n";
    std::exit(EXIT_FAILURE);
#endif
}
コード例 #7
0
ファイル: vector_Nd.cpp プロジェクト: suitmyself/Physika
VectorND<Scalar>::VectorND(const VectorND<Scalar> &vec2)
#ifdef PHYSIKA_USE_EIGEN_VECTOR
    :eigen_vector_Nx_(vec2.eigen_vector_Nx_)
#endif 
{
#ifdef PHYSIKA_USE_BUILT_IN_VECTOR
    allocMemory(vec2.dims());
    *this = vec2;
#endif  
}
コード例 #8
0
ファイル: vector_Nd.cpp プロジェクト: suitmyself/Physika
Scalar VectorND<Scalar>::dot(const VectorND<Scalar> &vec2) const
{
    unsigned int dim1 = (*this).dims();
    unsigned int dim2 = vec2.dims();
    if(dim1 != dim2)
        throw PhysikaException("vector dimension mismatch!");
    Scalar result = static_cast<Scalar>(0.0);
    for(unsigned int i = 0; i < dim1; ++i)
        result += (*this)[i]*vec2[i];
    return result;
}
コード例 #9
0
void FdmIccgSolver2::PreconditionerCompressed::solve(const VectorND& b,
                                                     VectorND* x) {
    const ssize_t size = static_cast<ssize_t>(b.size());

    const auto rp = A->rowPointersBegin();
    const auto ci = A->columnIndicesBegin();
    const auto nnz = A->nonZeroBegin();

    b.forEachIndex([&](size_t i) {
        const size_t rowBegin = rp[i];
        const size_t rowEnd = rp[i + 1];

        double sum = b[i];
        for (size_t jj = rowBegin; jj < rowEnd; ++jj) {
            size_t j = ci[jj];

            if (j < i) {
                sum -= nnz[jj] * y[j];
            }
        }

        y[i] = sum * d[i];
    });

    for (ssize_t i = size - 1; i >= 0; --i) {
        const size_t rowBegin = rp[i];
        const size_t rowEnd = rp[i + 1];

        double sum = y[i];
        for (size_t jj = rowBegin; jj < rowEnd; ++jj) {
            ssize_t j = static_cast<ssize_t>(ci[jj]);

            if (j > i) {
                sum -= nnz[jj] * (*x)[j];
            }
        }

        (*x)[i] = sum * d[i];
    }
}
コード例 #10
0
ファイル: matrix_MxN.cpp プロジェクト: JianpingCAI/Physika
VectorND<Scalar> MatrixMxN<Scalar>::operator* (const VectorND<Scalar> &vec) const
{
    unsigned int mat_row = (*this).rows();
    unsigned int mat_col = (*this).cols();
    unsigned int vec_dim = vec.dims();
    if(mat_col!=vec_dim)
    {
        std::cerr<<"Matrix*Vector: Matrix and vector sizes do not match!\n";
        std::exit(EXIT_FAILURE);
    }
    VectorND<Scalar> result(mat_row,0.0);
    for(unsigned int i = 0; i < mat_row; ++i)
    {
        for(unsigned int j = 0; j < mat_col; ++j)
            result[i] += (*this)(i,j)*vec[j];
    }
    return result;
}
コード例 #11
0
ファイル: vector_Nd.cpp プロジェクト: suitmyself/Physika
bool VectorND<Scalar>::operator== (const VectorND<Scalar> &vec2) const
{
    unsigned int dim1 = (*this).dims();
    unsigned int dim2 = vec2.dims();
    if(dim1 != dim2)
        return false;
    for(unsigned int i = 0; i < dim1; ++i)
    {
        if(is_floating_point<Scalar>::value)
        {
            if(isEqual((*this)[i],vec2[i])==false)
                return false;
        }
        else
        {
            if((*this)[i] != vec2[i])
                return false;
        }
    }
    return true;
}
コード例 #12
0
TEST(MatrixCsr, OperatorOverloadings) {
    const MatrixCsrD matA = {{1.0, 2.0, 3.0}, {4.0, 5.0, 6.0}};
    const MatrixCsrD addResult1 = matA + 3.5;
    for (size_t i = 0; i < 6; ++i) {
        EXPECT_EQ(i + 4.5, addResult1.nonZero(i));
    }

    const MatrixCsrD matC = {{3.0, -1.0, 2.0}, {9.0, 2.0, 8.0}};
    const MatrixCsrD addResult2 = matA + matC;
    const MatrixCsrD addAns1 = {{4.0, 1.0, 5.0}, {13.0, 7.0, 14.0}};
    EXPECT_TRUE(addAns1.isEqual(addResult2));

    const MatrixCsrD matD = {{3.0, 0.0, 2.0}, {0.0, 2.0, 0.0}};
    const MatrixCsrD addResult3 = matA + matD;
    const MatrixCsrD addAns2 = {{4.0, 2.0, 5.0}, {4.0, 7.0, 6.0}};
    EXPECT_TRUE(addAns2.isEqual(addResult3));

    const MatrixCsrD matE = {{3.0, 0.0, 2.0}, {0.0, 0.0, 0.0}};
    const MatrixCsrD addResult4 = matA + matE;
    const MatrixCsrD addAns3 = {{4.0, 2.0, 5.0}, {4.0, 5.0, 6.0}};
    EXPECT_TRUE(addAns3.isEqual(addResult4));

    const MatrixCsrD subResult1 = matA - 1.5;
    for (size_t i = 0; i < 6; ++i) {
        EXPECT_EQ(i - 0.5, subResult1.nonZero(i));
    }

    const MatrixCsrD subResult2 = matA - matC;
    const MatrixCsrD ans2 = {{-2.0, 3.0, 1.0}, {-5.0, 3.0, -2.0}};
    EXPECT_TRUE(ans2.isSimilar(subResult2));

    const MatrixCsrD matB = matA * 2.0;
    for (size_t i = 0; i < 6; ++i) {
        EXPECT_EQ(2.0 * (i + 1.0), matB.nonZero(i));
    }

    const VectorND vecA = {-1.0, 9.0, 8.0};
    const VectorND vecB = matA * vecA;
    const VectorND ansV = {41.0, 89.0};
    EXPECT_TRUE(ansV.isEqual(vecB));

    const MatrixCsrD matF = {{3.0, -1.0}, {2.0, 9.0}, {2.0, 8.0}};
    const MatrixCsrD matG = matA * matF;
    const MatrixCsrD ans3 = {{13.0, 41.0}, {34.0, 89.0}};
    EXPECT_TRUE(ans3.isEqual(matG));

    const MatrixCsrD matH = matA / 2.0;
    for (size_t i = 0; i < 6; ++i) {
        EXPECT_EQ((i + 1.0) / 2.0, matH.nonZero(i));
    }

    const MatrixCsrD matI = 3.5 + matA;
    for (size_t i = 0; i < 6; ++i) {
        EXPECT_EQ(i + 4.5, matI.nonZero(i));
    }

    const MatrixCsrD matJ = 1.5 - matA;
    for (size_t i = 0; i < 6; ++i) {
        EXPECT_EQ(0.5 - i, matJ.nonZero(i));
    }

    const MatrixCsrD matM = 2.0 * matA;
    for (size_t i = 0; i < 6; ++i) {
        EXPECT_EQ(2.0 * (i + 1.0), matM.nonZero(i));
    }

    const MatrixCsrD matP = 2.0 / matA;
    for (size_t i = 0; i < 6; ++i) {
        EXPECT_EQ(2.0 / (i + 1.0), matP.nonZero(i));
    }
}
コード例 #13
0
TEST(MatrixCsr, BinaryOperatorMethods) {
    const MatrixCsrD matA = {{1.0, 2.0, 3.0}, {4.0, 5.0, 6.0}};
    const MatrixCsrD addResult1 = matA.add(3.5);
    for (size_t i = 0; i < 6; ++i) {
        EXPECT_EQ(i + 4.5, addResult1.nonZero(i));
    }

    const MatrixCsrD matC = {{3.0, -1.0, 2.0}, {9.0, 2.0, 8.0}};
    const MatrixCsrD addResult2 = matA.add(matC);
    const MatrixCsrD addAns1 = {{4.0, 1.0, 5.0}, {13.0, 7.0, 14.0}};
    EXPECT_TRUE(addAns1.isEqual(addResult2));

    const MatrixCsrD matD = {{3.0, 0.0, 2.0}, {0.0, 2.0, 0.0}};
    const MatrixCsrD addResult3 = matA.add(matD);
    const MatrixCsrD addAns2 = {{4.0, 2.0, 5.0}, {4.0, 7.0, 6.0}};
    EXPECT_TRUE(addAns2.isEqual(addResult3));

    const MatrixCsrD matE = {{3.0, 0.0, 2.0}, {0.0, 0.0, 0.0}};
    const MatrixCsrD addResult4 = matA.add(matE);
    const MatrixCsrD addAns3 = {{4.0, 2.0, 5.0}, {4.0, 5.0, 6.0}};
    EXPECT_TRUE(addAns3.isEqual(addResult4));

    const MatrixCsrD subResult1 = matA.sub(1.5);
    for (size_t i = 0; i < 6; ++i) {
        EXPECT_EQ(i - 0.5, subResult1.nonZero(i));
    }

    const MatrixCsrD subResult2 = matA.sub(matC);
    const MatrixCsrD ans2 = {{-2.0, 3.0, 1.0}, {-5.0, 3.0, -2.0}};
    EXPECT_TRUE(ans2.isSimilar(subResult2));

    const MatrixCsrD matB = matA.mul(2.0);
    for (size_t i = 0; i < 6; ++i) {
        EXPECT_EQ(2.0 * (i + 1.0), matB.nonZero(i));
    }

    const VectorND vecA = {-1.0, 9.0, 8.0};
    const VectorND vecB = matA.mul(vecA);
    const VectorND ansV = {41.0, 89.0};
    EXPECT_TRUE(ansV.isEqual(vecB));

    const MatrixCsrD matF = {{3.0, -1.0}, {2.0, 9.0}, {2.0, 8.0}};
    const MatrixCsrD matG = matA.mul(matF);
    const MatrixCsrD ans3 = {{13.0, 41.0}, {34.0, 89.0}};
    EXPECT_TRUE(ans3.isEqual(matG));

    const MatrixCsrD matH = matA.div(2.0);
    for (size_t i = 0; i < 6; ++i) {
        EXPECT_EQ((i + 1.0) / 2.0, matH.nonZero(i));
    }

    const MatrixCsrD matI = matA.radd(3.5);
    for (size_t i = 0; i < 6; ++i) {
        EXPECT_EQ(i + 4.5, matI.nonZero(i));
    }

    const MatrixCsrD matJ = matA.rsub(1.5);
    for (size_t i = 0; i < 6; ++i) {
        EXPECT_EQ(0.5 - i, matJ.nonZero(i));
    }

    const MatrixCsrD matK = {{3.0, -1.0, 2.0}, {9.0, 2.0, 8.0}};
    const MatrixCsrD matL = matA.rsub(matK);
    const MatrixCsrD ans4 = {{2.0, -3.0, -1.0}, {5.0, -3.0, 2.0}};
    EXPECT_EQ(ans4, matL);

    const MatrixCsrD matM = matA.rmul(2.0);
    for (size_t i = 0; i < 6; ++i) {
        EXPECT_EQ(2.0 * (i + 1.0), matM.nonZero(i));
    }

    const MatrixCsrD matP = matA.rdiv(2.0);
    for (size_t i = 0; i < 6; ++i) {
        EXPECT_EQ(2.0 / (i + 1.0), matP.nonZero(i));
    }
}