【问题标题】:template style matrix implementation in cc中的模板样式矩阵实现
【发布时间】:2010-04-05 09:49:34
【问题描述】:

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

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++ 中。 抱歉没有说清楚。

【问题讨论】:

  • 那为什么是 C++ 标签呢?而 C 甚至没有模板!。
  • 这看起来像是一种情况,您可以合法地滥用预处理器,通过宏和令牌粘贴为您提供穷人的模板模拟。
  • 如果它是合法的,那么它不是滥用。这看起来像是您可以合法地诉诸预处理器的使用的情况;-)
  • @Steve - 也许是这样,但我怀疑在实施过程中仍然会口头滥用预处理器。 ;-)
  • @Paul R,滥用,你的意思是它不完全是类型安全的吗?我认为这是给定的?

标签: c alloc generic-collections


【解决方案1】:

在 C 中?凌乱,但可以使用宏魔法。 (顺便说一句,C++ 是更好的选择)。

#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*x_size+y] 而不是ary[a][b]。如果需要,您可以将所有这些都包含在更多的宏中,但在内存管理和访问方面都更加高效。

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

    • 我不会使用vector&lt;vector&lt;T&gt;&gt;。有内存碎片。恕我直言,vector&lt;T&gt;mData[j*width+i] 更好。
    • @Alexey 就像我说的,我不会把它作为生产质量提出来。我想避免计算索引,因为我知道在某些时候我会以错误的方式得到它:-)
    【解决方案3】:

    正如之前的 cmets 所建议的,使用线性内存的行主矩阵:

    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];
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-09-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-21
      相关资源
      最近更新 更多