我正在使用C进行一些科学计算,并且需要移动很多向量。
我已经定义了表格
的一些基本的乘法和加法函数add(int size, double *out, double *x, double *y)
但是对于复杂的操作,代码很快就变得很难阅读。
是否可以定义内联运算符(V1 + V2)?或者任何一般的最佳实践,可以更容易地检查数学错误的代码?也许是一些#define shenanigans?
答案 0 :(得分:4)
起初我认为这是一个C ++问题出于某种原因!
如果您可以使用C ++,您可能可以使用STL数组(其中大小是模板参数,而不是存储值)。
它可能看起来像这样:
std::array<double, 7> a = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0};
std::array<double, 7> b = {0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0};
auto c = a + b;
auto d = a + b + c;
您可以为operator +定义运算符重载。 E.g:
#include <array>
// ...
// (version 1) returns a new copy/temporary
template <class T, size_t size>
std::array<T, size> operator+(const std::array<T, size>& a,
const std::array<T, size>& b)
{
std::array<T, size> c;
// add them however you want; simple version:
for (size_t i = 0; i < size; ++i)
{
c[i] = a[i] + b[i];
}
return c;
}
// (version 2) no temporaries via rvalue ref/move semantic
template <class T, size_t size>
std::array<T, size>&& operator+(std::array<T, size>&& a,
const std::array<T, size>& b)
{
for (size_t i = 0; i < size; ++i)
{
a[i] += b[i];
}
return std::move(a);
}
这样:
auto c = a + b; // invokes version 1
auto d = a + b + c; // invokes version 1 for (b+c)
// and then version 2 for a+(temp)
所以你在任何一系列操作中最多只能使用一个临时文件。
std :: array的内存布局应该与本机数组相同,因此您应该能够很容易地将这些代码“注入”到现有程序中(通过(ab)使用强制转换,typedef或预处理器)如果你想触及最少量的现有代码。
答案 1 :(得分:3)
如果您不介意问题的非标准解决方案,英特尔编译器支持C中数组表示法的扩展。这是一个链接:
基本上,您可以编写如下代码:
int A[4] = { 1, 2, 3, 4 };
int B[4] = { 4, 3, 2, 1 };
int C[4];
C[:] = A[:] + B[:];
它还提供了许多数学函数的矢量版本,因此您可以执行以下操作:
B[:] = cosf(C[:]);
作为一个额外的好处,如果您编写这样的代码,它会在SSE / AVX指令中进行矢量化。
答案 2 :(得分:2)
这称为“运算符重载”,它是不 C的一个特性。但 是C ++的一个特性。如果C ++是一个选项,那么有很多关于如何重载运算符的教程。有些人认为它是邪恶的,因为:
当代码脱离上下文时,很难说出实际会发生什么。例如,您可以在那里看到操作符,但是您如何知道它们是内置的还是超载的?
例如,有可能重载运算符并对它们应用不常见的意义(这是我在实际代码中看到的),你可以重载“/”运算符(除法运算符)到充当以独立于操作系统的方式处理文件名的类的路径分隔符:
Filename f = Filename::MainFileSystem() / "folder1" / "folder2" / "file.txt";
不要这样做。
使用重载运算符也有好处:
代码可以大大简化。您可以使用
而不是多个函数调用result = vec1 + vec2 + vec3;
请注意,如上所述,很难通过查看该行代码来判断是否会调用任何函数,但这种难度是否超过简化的好处是主观的。
您可以执行一些漂亮的技巧,例如smart pointers,它们可以为您提供附加功能,而无需修改运算符的原始语义。
答案 3 :(得分:1)
是否可以定义内联运算符(V1 + V2)?
没有。但它是在C ++中。