Program Listing for File block_matrix.hpp

Return to documentation for file (src_util/block_matrix.hpp)

#ifndef block_matrix_h
#define block_matrix_h

#include <iostream>
#include <vector>

#include "matrix.hpp"

template<typename T>
struct block_matrix
{
    size_t r;
    size_t c;
    vector<matrix<T>> block;
    vector<size_t> cumul_r;
    vector<size_t> cumul_c;

    block_matrix(): r(0),c(0)
    {
        set_size();
    }

    block_matrix(size_t n)
    {
        block.assign(n, matrix<T>());
    }

    block_matrix(vector<size_t> dim)
    {
    block.assign(dim.size(), matrix<T>());
    for(size_t i=0; i<dim.size(); i++) block[i].set_size(dim[i]);
    set_size();
    }

    block_matrix(vector<int> dim)
    {
    block.assign(dim.size(), matrix<T>());
    for(size_t i=0; i<dim.size(); i++) block[i].set_size(dim[i]);
    set_size();
    }

  block_matrix(vector<matrix<T> > &_block) : block(_block)
    {
    set_size();
    }

    block_matrix& operator=(const block_matrix<T>& A)
    {
        r = A.r;
        c = A.c;
        cumul_r = A.cumul_r;
        cumul_c = A.cumul_c;
        block = A.block;
        return(*this);
    }


    void set_size(){
        cumul_r.clear();
        cumul_r.reserve(block.size());
        r = 0;
        for(size_t i=0; i<block.size(); ++i){
            cumul_r.push_back(r);
            r += block[i].r;
        }
        cumul_c.clear();
        cumul_c.reserve(block.size());
        c = 0;
        for(size_t i=0; i<block.size(); ++i){
            cumul_c.push_back(c);
            c += block[i].c;
        }
    }

    inline T operator()(const size_t &i, const size_t &j)const{
        size_t I= block.size()-1; while(cumul_r[I]>i) I--;
        size_t J= block.size()-1; while(cumul_c[J]>i) J--;
        if(I != J) return(0.0);
        else return (block[I])(i-cumul_r[I],j-cumul_c[I]);
    }

    matrix<T> build_matrix(){
    matrix<T> A(r,c);
        for(size_t i=0; i<block.size(); i++){
            for(size_t j=0; j<block[i].r; j++){
                for(size_t k=0; k<block[i].c; k++){
                    A(cumul_r[i]+j,cumul_c[i]+k) = block[i](j,k);
                }
            }
        }
    return A;
    }


    template <typename S>
    block_matrix<T>& operator-=(const block_matrix<S> &A){
        for(size_t i=0; i<block.size(); ++i) block[i].v -= A.block[i].v;
        return *this;
    }

    template <typename S>
    block_matrix<T>& operator+=(const block_matrix<S> &A){
        for(size_t i=0; i<block.size(); ++i) block[i].v += A.block[i].v;
        return *this;
    }

    template <typename S>
    void add(matrix<S> &Y, T z) const
    {
        for(size_t ib=0; ib<block.size(); ++ib){ // loop over sets of rows
            size_t br = block[ib].r;
            size_t bc = block[ib].c;
            size_t R = cumul_r[ib];
            size_t C = cumul_c[ib];
            for(size_t i=0; i<br; ++i){
                for(size_t j=0; j<bc; ++j){
                    Y(R+i,C+j) += z*block[ib](i,j);
                }
            }
        }
    }

    void add(T d){
        for(size_t i=0; i<block.size(); ++i) block[i].add(d);
    }


    void clear(){
        for(size_t i=0; i<block.size(); ++i) block[i].clear();
    }

    double diff_sq(const block_matrix<T> &A)
    {
        double z=0.0;
        for(size_t i = 0; i < block.size(); ++i) z += block[i].diff_sq(*A.block[i]);
        return(z);
    }

    void inverse()
    {
        for(size_t i = 0; i < block.size(); ++i) block[i].inverse();
    }


    T trace(){
        T z(0.0);
        for(size_t i = 0; i < block.size(); ++i) z += block[i].trace();
        return z;
    }

    block_matrix<T>& operator+=(const double a){for(size_t i=0; i<block.size(); ++i) block[i].add(a); return *this;}
    block_matrix<T>& operator+=(const Complex a){for(size_t i=0; i<block.size(); ++i) block[i].add(a); return *this;}
    block_matrix<T>& operator-=(const double a){for(size_t i=0; i<block.size(); ++i) block[i].add(-a); return *this;}
    block_matrix<T>& operator-=(const Complex a){for(size_t i=0; i<block.size(); ++i) block[i].add(-a); return *this;}



    template <typename S, typename U>
    void mult_left(const matrix<S> &X, matrix<U> &Y) const
    {
        for(size_t ib=0; ib<block.size(); ++ib){ // loop over sets of rows of Y
            for(size_t i=0; i<block[ib].r; ++i){
                for(size_t j=0; j<X.c; ++j){
                    U z(0.0);
                    for(size_t k=0; k<block[ib].c; ++k){
                        z += block[ib](i,k)*X(k+cumul_c[ib],j);
                    }
                    Y(i+cumul_r[ib],j) = z;
                }
            }
        }
    }

    template <typename S, typename U>
    void mult_right(const matrix<S> &X, matrix<U> &Y) const
    {
        for(size_t ib=0; ib<block.size(); ++ib){ // loop over sets of rows of Y
            for(size_t i=0; i<block[ib].c; ++i){
                for(size_t j=0; j<X.r; ++j){
                    U z(0.0);
                    for(size_t k=0; k<block[ib].r; ++k){
                        z += block[ib](k,i)*X(j,k+cumul_r[ib]);
                    }
                    Y(j,i+cumul_c[ib]) = z;
                }
            }
        }
    }




    template<typename S, typename U>
    void simil(matrix<S>  &A, const matrix<U> &B)
    {
        A.zero();
        for(size_t ij=0; ij<block.size(); ij++){
            size_t J_r = (int)cumul_r[ij];
            size_t J_c = (int)cumul_c[ij];
            for(size_t j = 0; j < block[ij].c; j++){
                for(size_t ii=0; ii<block.size(); ii++){
                    size_t I_r = (int)cumul_r[ii];
                    size_t I_c = (int)cumul_c[ii];
                    for(size_t i = 0; i < block[ii].c; ++i){
                        S z = 0.0;
                        for(size_t k = 0; k < block[ii].r; ++k){
                            S zz = 0.0;
                            for(size_t l = 0; l < block[ij].r; ++l){
                                zz += block[ij](l,j)*B(k+I_r,l+J_r);
                            }
                            z += zz*conjugate(block[ii](k,i));
                        }
                        A(i+I_c,j+J_c) += z;
                    }
                }
            }
        }
    }




    template<typename S, typename U>
    void simil_conjugate(matrix<S>  &A, const matrix<U> &B)
    {
        A.zero();
        for(size_t ij=0; ij<block.size(); ij++)
        {
            size_t J_r = (int)cumul_r[ij];
            size_t J_c = (int)cumul_c[ij];
            for(size_t j = 0; j < block[ij].c; j ++)
            {
                for(size_t ii=0; ii<block.size(); ii++)
                {
                    size_t I_r = (int)cumul_r[ii];
                    size_t I_c = (int)cumul_c[ii];
                    for(size_t i = 0; i < block[ii].c; ++i)
                    {
                        S z = 0.0;
                        for(size_t k = 0; k < block[ii].r; ++k)
                        {
                            S zz = 0.0;
                            for(size_t l = 0; l < block[ij].r; ++l)
                            {
                                zz += conjugate(block[ij](j,l))*B(k+I_r,l+J_r);
                            }
                            z += zz*conjugate(block[ii](i,k));
                        }
                        A(i+I_c,j+J_c) += z;
                    }
                }
            }
        }
    }



};

template <typename T>
std::ostream & operator<<(std::ostream &flux, block_matrix<T> &A){
    for(size_t i=0; i<A.block.size(); ++i) flux << A.block[i];
    return flux;
}


#endif