8

我正在编写一些代码来集成 ODE。这个问题既是对编码建议的请求,也是对解决方案的请求,因此,如果您对我将要提供的建议有替代建议,请告诉我!

ODE 积分器要集成的“对象”以 6 个“块”的形式出现……原因是我有一个双精度的 std::vector,它们按以下方式排列:

前 3 个双精度值是位置坐标;x、y 和 z。接下来的 3 个双精度是速度坐标;x、y 和 z。

所以,现在你知道了,我有一个函数,它接受成对的“位置” “”“向量”“”作为参数并返回某种结果......看看我要去哪里?

目前,该函数需要 2 批位置坐标,方式如下:

std::vector<double> magic_gravity_formula(const std::vector<double> &r1,
          const std::vector<double> &r2, const double m1, const double m2)

我不想将 3 组中的所有数据复制到新向量中——这是一种疯狂(而且非常慢)的编程方式。

可以改为使用指向原始数据的指针......并且只需将指针传递给 x 坐标(3 个双精度块中的第一项) - 这对我来说似乎还可以,但也许有更好的方法?有点像 Python 或 Matlab 数组切片?我可以做这样的事情吗?

我有点想传递一个新的向量(或某种包装类?),从已经存储在数组中的数据创建......有点像

std::vector<double> sub_section_of_data = data[0..2] // Obviously pseudocode!

好的,所以上面的内容是荒谬的,因为可能实现该语法的语言仍然会进行复制操作,这可能很慢 - 这正是我试图避免的......

所以是的,我不确定在这里进行的最佳方式 - 任何人都可以提出一个“好的”解决方案吗?(以非主观方式!)

编辑:要说清楚 - 问题是我不想做类似的事情:

std::vector<double> r1_temp;
r1_temp.push_back(data[0]); // Copy ! Bad !
r1_temp.push_back(data[1]);
r1_temp.push_back(data[2]);

... same for an r2 ...

std::vector<double> force = magic_gravity_formula(r1, r2, m1, m2);

编辑 2:考虑编译器选项 - 编译器是否会通过以下方式更改函数以接受参数来为我优化我的代码:

std::vector<double> super_gravity_formula(double x1, double y1, double z1, double x2, double y2, double z2, double m1, double m2)

在这种情况下,也许这个问题并不重要?(除了形成“让你的代码看起来很好读”的观点。)

编辑3:因此它仍然很重要。

4

4 回答 4

8

您想要查看现有矢量。

std::experimental::array_view<T>,或自己滚动。

数组视图是一对T*, 和 访问器,可让您将其视为数组operator[] .begin() .back() size() empty()等。

这是我推出的许多此类实现之一。那个有点重,具有range<Iterator>自适应处理随机访问迭代器的视图,并且array_view<T>继承自range<T*>.

如果它不起作用,请在“yakk”上搜索另一个帖子,其中包含“array_view”一词或自己调试。我已经写了至少六次,或多或少有调试,有不同的const正确性规则。

拥有它后,{ vec.data()+index, vec.data()+index+3 }将构造一个array_view<double>开销几乎为零的。

于 2015-06-08T20:02:46.447 回答
1

如果你想要的是向量,在数学意义上,6 个 double 类型的元素std::vector<double>可能不是最有效的表示。我会继续定义一个 3D 点,然后将位置 + 速度定义为:

struct point {
   double x, y, z;
};
struct position_and_velocity {
   point pos;
   point vel;
};

对这种类型进行操作可能比对向量进行操作(无动态分配)更有效,您可以将其作为values进行操作。这个结构的完整副本可能比将第一个元素插入 中更便宜,并且比提供两个指向数组的指针来获得切片std::vector要慢一点但不多。

此外,它更不容易出错,因为在对数组进行切片的情况下,您可能会错误地使用错误的值并最终得到诸如(伪代码)之类的东西slice[1..3],它是两个位置坐标和一个速度坐标(可能不是- 感性的)。

函数签名是程序二进制接口的一部分,编译器不会更改函数签名,除非它内联代码。此外,我非常怀疑编译器是否会在任何转换中删除向量固有的动态分配(除非它可以删除整个变量)。

于 2015-06-08T21:37:15.057 回答
0

由于代码要求const std::vector<double> &您不能更聪明。

否则(如果库函数更通用),您可以轻松传递一个范围(参见例如 Boost Range,但您可以轻松地一次性使用一个向量子范围,就像boost::string_refor std::string_view

于 2015-06-08T20:03:50.823 回答
0

'我可以使用指向原始数据的指针......并且只需将指针传递给 x 坐标'。

你自己回答了你的问题。std::algorithms 什么都不做,否则。

于 2015-06-08T20:06:04.073 回答