2014/01/22

c++ テンプレートメタプログラミング 3 静的多様性を用いた行列の足し算



いくつでも行列足し算できる奴も出来た. gcc-4.8.0で動作確認, 4.3.4ではコンパイル出来なかった.

元ネタ
http://itee.uq.edu.au/~conrad/misc/sanderson_templates_lecture_uqcomp7305.pdf
#include<iostream>

template< typename T1, typename T2 >
class Glue;

template< typename derived>
struct Base {
    const derived & get_ref() const{
        return static_cast<const derived&>(*this);
    }
};

class Matrix : public Base < Matrix >{
public:
    int rows;
    int cols;
    double *data;
  
    Matrix(){}
    Matrix( int in_rows, int in_cols ){
        set_size( in_rows, in_cols );
    }
    void set_size( int in_rows, int in_cols ){
        rows = in_rows;
        cols = in_cols;
        data = new double [rows*cols];
        for( int i=0; i<rows*cols; i++ ) data[i] = 1.0;
    }

    Matrix( const Matrix & X );
    const Matrix& operator=( const Matrix & X );

    template< typename T1, typename T2 >
    Matrix( const Glue<T1, T2> & X );

    template< typename T1, typename T2 >
    const Matrix & operator=( const Glue<T1, T2> & X );
};

template< typename T1, typename T2 >
class Glue : public Base< Glue<T1,T2> >{
public:
    const T1 & A;
    const T2 & B;

    Glue( const T1 & in_A, const T2 & in_B ): A(in_A), B(in_B) {

    }
};


template< typename T1, typename T2 >
inline const Glue< T1, T2 >
operator+( const Base<T1>&A, const Base<T2> & B ){
    return Glue< T1, T2 >( A.get_ref(), B.get_ref() );
}

template< typename T1 >
struct depth_lhs{
    static const int num = 0;
};

template< typename T1, typename T2 >
struct depth_lhs< Glue<T1, T2 > >{
    static const int num = 1 + depth_lhs<T1>::num;
};

template< typename T1 >
struct mat_ptrs{
    static const int num = 0;

    inline static void
    get_ptrs( const Matrix** ptrs, const T1 & X ){
        {
            ptrs[0] = reinterpret_cast<const Matrix*>(&X);
        }
    }
};

template< typename T1, typename T2 >
struct mat_ptrs< Glue<T1, T2> >
{
    static const int num = 1 + mat_ptrs<T1>::num;

    inline static void
    get_ptrs( const Matrix** in_ptrs, const Glue<T1,T2>& X ){
        mat_ptrs<T1>::get_ptrs(in_ptrs, X.A );

        in_ptrs[num] = reinterpret_cast< const Matrix*>( & X.B );
    }
};

template< typename T1, typename T2 >
const Matrix & Matrix::operator=( const Glue<T1,T2>& X ){
    int i,j;
    double sum;
    int N = 1 + depth_lhs < Glue<T1,T2> >::num;
    const Matrix* ptrs[N];
    mat_ptrs< Glue<T1,T2> >::get_ptrs(ptrs,X);
  
    int r = ptrs[0]->rows;
    int c = ptrs[0]->cols;

    set_size( r, c );

    for( j=0; j<r*c; ++j ){
        double sum = ptrs[0]->data[j];
        for( i=1; i<N; ++i ){
            sum += ptrs[i]->data[j];
        }
        data[j] = sum;
    }
    return *this;
}

int main(){
    Matrix A(2,2);
    Matrix B(2,2);
    Matrix C(2,2);
    Matrix D(2,2);
    Matrix X(2,2);

    X = A+B+C+D;

    for( int i=0; i<4; i++ ) std::cout << X.data[i] << std::endl;
return 0;}

0 件のコメント:

コメントを投稿

まとめページ

      

リンク

The Wizard of Science
友達のブログ文化人類学とか難しい話をしております。あとホームページから自作ゲームも配布。