gpt4 book ai didi

c++ - 将二进制文件加载到 Eigen 矩阵时删除可能冗余的模板参数

转载 作者:行者123 更新时间:2023-11-30 04:09:29 24 4
gpt4 key购买 nike

我想将一个包含许多无符号 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),我认为应该使用第一个模板参数来推断。

问题 有没有办法消除read_data看似多余的第二个模板参数? ?

此外,我传递矩阵引用的方法是否只是为了在 read_data 中调整它的大小?功能(使用创建对矩阵的可修改引用以通过 derived() 调整其大小的冗长且令人困惑的成语)正确的方法?我意识到这会动态分配内存,这很好,但我认为它没有做任何浪费——对吗?

(讨论是否有人希望看到此代码的其他改进?我是 C 或 Python 数字编码器;在 C 中,我只处理 void* 数组并传递一个额外的函数参数,告诉函数每个标量的大小;使用 Python 我会做 numpy.fromfile('path/to/file.bin', dtype=numpy.uint16) 并完成它。但我想通过 Eigen 和 C++ 正确地完成它。)

注意。我使用矩阵而不是 vector ,因为稍后我会将它们调整为矩形矩阵。

NB2。在 Fixed Sized Eigen types as parameters提倡使用标量类型对函数进行模板化的概念。我并不反对这种做法,我选择通过read_data一个矩阵引用而不是让它返回一个 Matrix 对象,因为我想要指示错误的整数返回值——尽管现在我意识到我应该做出这些异常(exception)。

NB3。在 c++ check for nested typedef of a template parameter to get its scalar base type我认为,一组精心制作的辅助类用于为模板化的 实现类似的效果。我很好奇这里是否可以使用更简单的方法来实现模板化的函数

NB4。我知道的一个简单改进是 typedeffing Matrix<uint16_t, Dynamic, Dynamic>以减少冗长。

最佳答案

我认为 Matrix<uint16_t, Dynamic, Dynamic>应该有一个 typedef检索 uint16_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);

关于c++ - 将二进制文件加载到 Eigen 矩阵时删除可能冗余的模板参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21200209/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com