c中的模板样式矩阵实现

时间:2010-04-05 09:49:35

标签: c alloc generic-collections

我不时使用以下代码生成矩阵式数据结构

typedef double myType;

typedef struct matrix_t{                                                             |Compilation started at Mon Apr  5 02:24:15
  myType **matrix;                                                                   |
  size_t x;                                                                          |gcc structreaderGeneral.c -std=gnu99 -lz
  size_t y;                                                                          |
}matrix;                                                                             |Compilation finished at Mon Apr  5 02:24:15
                                                                                     |
                                                                                     |
matrix alloc_matrix(size_t x, size_t y){                                             |
  if(0)                                                                              |
    fprintf(stderr,"\t-> Alloc matrix with dim (%lu,%lu) byteprline=%lu bytetotal:%l\|
u\n",x,y,y*sizeof(myType),x*y*sizeof(myType));                                       |
                                                                                     |
  myType **m = (myType **)malloc(x*sizeof(myType **));                               |
  for(size_t i=0;i<x;i++)                                                            |
    m[i] =(myType *) malloc(y*sizeof(myType *));                                     |
                                                                                     |
  matrix ret;                                                                        |
  ret.x=x;                                                                           |
  ret.y=y;                                                                           |
  ret.matrix=m;                                                                      |
  return ret;                                                                        |
} 

然后,如果我的矩阵中的条目需要不同类型,我会相应地更改我的typedef。

现在我需要2个不同类型的矩阵,一个简单的解决方案是复制/粘贴代码,但是有一些方法可以进行更通用的实现。

由于

编辑: 我应该澄清它在c而不是c ++中。 很抱歉没有说清楚。

3 个答案:

答案 0 :(得分:3)

在C?凌乱,但宏观魔术可能。 (你已经到了C ++是更好的选择,BTW)。

#define DECL_MATRIX(type,name) \
    typedef struct matrix_##type##_t {             \
        type **matrix;                             \
        size_t x;                                  \
        size_t y;                                  \
    } name;                                        \
    name alloc_##name(size_t x,size_t y)

#define DEFINE_MATRIX_OPS(type,name) \
    struct matrix_##type##_t                       \
    alloc_##name(size_t x, size_t y) {             \
        size_t i;                                  \
        struct matrix_##type##_t ret;              \
        type **m;                                  \
                                                   \
        m = (type **)malloc(x*sizeof(type *));     \
        for(size_t i=0;i<x;i++)                    \
            m[i] =(type *) malloc(y*sizeof(type)); \
        ret.x=x;                                   \
        ret.y=y;                                   \
        ret.matrix=m;                              \
        return ret;                                \
    }

然后你会像这样使用这些:

// At the top level of the file
DECL_MATRIX(double, dmat);
DECL_MATRIX(int, imat);
DEFINE_MATRIX_OPS(double, dmat);
DEFINE_MATRIX_OPS(int, imat);

// In a function
dmat d = alloc_dmat(3,3);
imat i = alloc_imat(2,6);

作为设计说明,对于固定大小的矩阵来说,最好将元素的内存分配为单个块,并使用一点数学来索引它们。因此,您使用ary[a][b]代替ary[a*x_size+y]。如果需要,您可以将其全部包含在更多宏中,但无论是在内存管理还是访问方面,它都更有效。

答案 1 :(得分:1)

我需要一个非常简单的矩阵来进行一次性项目,然后把这个项目搞砸了。这不是我所说的生产质量,但它可能会给你一些想法:

template <typename T>
class Matrix2D {

    public:

        Matrix2D( unsigned int  width, unsigned int  height,
                            const T & v  = T() ) {
            if ( width == 0 || height == 0 ) {
                throw std::out_of_range( "Invalid Matrix2D size ");
            }
            for ( unsigned int x = 0; x < width; x++ ) {
                mData.push_back( std::vector<T>( height, v ) );
            }
        }

        T & operator()( unsigned int x, unsigned int y ) {
            if ( x >= Width() || y >= Height() ) {
                throw std::range_error( "Invalid Matrix2D index" );
            }
            return mData[x][y];
        }

        const T & operator()( unsigned int x, unsigned int y ) const {
            if ( x >= Width() || y >= Height() ) {
                throw std::range_error( "Invalid Matrix2D index" );
            }
            return mData[x][y];
        }


        void Clear( const T & v  = T() ) {
            for ( unsigned int x = 0; x < Width(); x++ ) {
                for ( unsigned int y = 0; y < Height(); y++ ) {
                    mData[x][y] = v;
                }
            }
        }

        unsigned int Width() const {
            return mData.size();
        }

        unsigned int Height() const {
            return mData[0].size();
        }

        void DumpOn( std::ostream & os ) {
            for ( unsigned int y = 0; y < Height(); y++ ) {
                for ( unsigned int x = 0; x < Width(); x++ ) {
                    os << '[' << mData[x][y] << ']';
                }
                os << "\n";
            }
        }

    private:

        std::vector <std::vector  <T> > mData;
};

答案 2 :(得分:0)

正如之前的评论所建议的那样,使用线性存储器的行主矩阵:

template<typename T, unsigned int DIM>
class matrix {
    public:
        matrix<T,DIM>() {
            matrix(0);
        }
        matrix<T,DIM>(const T* v) {
            for (unsigned int i=0; i<DIM*DIM; ++i)
                value[i] = v[i];
        }
        matrix<T,DIM>(T v) {
            for (unsigned int i=0; i<DIM*DIM; ++i)
                value[i] = v;
        }
        T& operator[](int index) {
            assert(index >= 0 && index < (int)(DIM*DIM));
            return value[index];
        }

        // and so on...

    private:
        T value[DIM * DIM];
}