将二进制文件加载到eigen矩阵中时,请删除潜在的冗余模板参数

Removing potentially redundant template parameters when loading a binary file into Eigen matrix

本文关键字:删除 冗余 参数 加载 二进制文件 eigen      更新时间:2023-10-16

我想读一个普通的二进制文件,其中包含许多未签名的16位整数到特征矩阵中,我写了一个模板的实用程序来做到这一点。这就是呼叫者的样子:

Matrix<uint16_t, Dynamic, Dynamic> data;
int retval = read_data<Matrix<uint16_t, Dynamic, Dynamic>, uint16_t>(
    argv[1], data);

这就是read_data的样子:

template <typename Derived, typename Scalar> // Per @Jarod42, get rid of Scalar here (*)
int read_data(const char* const fname, MatrixBase<Derived>& data) {
    // (*) If we don't have Scalar as a template, just uncomment this:
    // typedef typename Derived::Scalar Scalar;
    ifstream fin(fname, ios::binary);
    if (!fin) {
        return 2;
    }
    fin.seekg(0, fin.end);
    long long bytes = fin.tellg();
    if (bytes % sizeof(Scalar) != 0) {
        // The available number of bytes won't fill an even number of Scalar
        // values
        return 3;
    }
    long long nscalars = bytes / sizeof(Scalar);
    // See http://forum.kde.org/viewtopic.php?f=74&t=107551
    MatrixBase<Derived>& data_edit = const_cast<MatrixBase<Derived>&>(data);
    data_edit.derived().resize(nscalars, 1);
    Scalar* buffer = new Scalar[nscalars]; // Switched to vector per @Casey
    fin.seekg(0, fin.beg);
    fin.read(reinterpret_cast<char*>(buffer), bytes);
    if (!fin) {
        // All data not read. fin.gcount() will indicate bytes read.
        return 4;
    }
    for (long long idx = 0; idx < nscalars; ++idx) {
        data_edit(idx) = buffer[idx];
    }
    return 0;
}

简要

  1. 打开文件,
  2. 获得其大小,
  3. 动态分配一个数组以存储所有数据,
  4. 将文件读取到数组中,
  5. 阵列的内容被复制到矩阵中。

这是合理的,它有效(尽管我对改进的建议很开放),但是我认为该功能具有一个太多的模板参数, ,呼叫者中的函数调用也是冗长。我认为应该有一种消除第二个模板参数的方法,该参数仅用于告诉 read_data每个标量的字节数(在uint16_t的情况下为2),我相信应该使用第一个模板参数来下降。p> 问题有没有办法消除看似冗余的第二个模板参数到read_data

另外,我的方法是传递矩阵参考仅在read_data函数中调整它的大小(使用详细和令人困惑的习语来创建对矩阵的可修改引用,以通过derived()进行调整大小)。?我意识到这动态分配了记忆,这很好,但是我认为这没有做任何浪费的事情---正确?

讨论此代码是否还有其他改进?我是C或Python数字编码器;在C中,我只是处理void*阵列并传递额外函数参数告诉每个标量的函数;使用Python,我会做numpy.fromfile('path/to/file.bin', dtype=numpy.uint16)并使用它。但是我想通过EIGEN和C 做正确的操作。)

nb。我使用矩阵而不是向量,因为稍后我将它们调整到矩形矩阵中。

nb2。在固定尺寸的特征类型中,作为参数,促进使用标量类型模板函数的概念。我并不反对这种方法,我选择通过read_data矩阵参考,而不是使其返回矩阵对象,因为我想要整数返回值指示错误 - - 现在我意识到我应该做出这些例外。

>

nb3。在C 检查模板参数的嵌套类型中,以获取其标量基本类型,我认为,精心设计的辅助类别集用于对模板的类似效果。我很好奇是否可以在此处使用更简单的方法,用于模板函数

nb4。我知道的一个简单的改进是键入Matrix<uint16_t, Dynamic, Dynamic>来减少冗长的速度。

我认为Matrix<uint16_t, Dynamic, Dynamic>应该具有typedefuint16_t。如果是这样,您可以作为第一行写(假设是type):

typedef typename Derived::type Scalar;

如果没有typedef,则可以为此写一个特征:

template <typename> struct matrix_type;
template <typename T, typename U1, typename U2>
struct matrix_type<Matrix<T, U1, U2> >
{
    typedef T type;
    typedef U1 type1;
    typedef U2 type2;
};

然后写

typedef typename matrix_type<Derived>::type Scalar;

注意:如果您已按其他顺序编写了参数

template <typename Derived, typename Scalar>
int read_data(const char* const fname, MatrixBase<Derived>& data);

您可以写(因为可以推论最后一个参数):

Matrix<uint16_t, Dynamic, Dynamic> data;
int retval = read_data<uint16_t>(argv[1], data);

现在,参数已过时,您可以直接写入:

Matrix<uint16_t, Dynamic, Dynamic> data;
int retval = read_data(argv[1], data);

您可能想查看eigen中的地图。它直接将记忆带入了一个。

tutorialmapclass.html"> http://eigen.tuxfamily.org/dox/group_tutorialmapclass.html

要构建一个MAP变量,您还需要其他两个信息:定义系数数组的内存区域的指针,以及矩阵或向量的所需形状。例如,要定义一个在编译时确定尺寸的浮子矩阵,您可以执行以下操作:

MAP MF(PF,行,列);