3

私はCを使用して科学計算を行っており、多くのベクトルを移動する必要があります。

フォームのいくつかの基本的な乗算および加算関数を定義しました

add(int size, double *out, double *x, double *y)

しかし、複雑な操作の場合、コードはすぐに長くなり、読みにくくなります。

インライン演算子(V1 + V2)を定義することは可能ですか?または、数学エラーのチェックコードを見つけやすくする一般的なベストプラクティスはありますか?おそらくいくつかの#defineshenanigans?

4

4 に答える 4

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+の演算子オーバーロードを定義できます。例えば:

#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)

したがって、操作のチェーンで一時的に使用するのは最大で1つです。

std :: arrayのメモリレイアウトはネイティブ配列と同じである必要があるため、必要に応じて、このコードを既存のプログラムに(キャスト、typedef、またはプリプロセッサを(ab)使用して)非常に簡単に「挿入」できるはずです。最小限の既存のコードに触れること。

于 2012-05-04T02:02:11.707 に答える
3

この問題の非標準的な解決策を気にしないのであれば、インテル®コンパイラーはCでの配列表記の拡張機能をサポートしています。リンクは次のとおりです。

http://software.intel.com/sites/products/documentation/studio/composer/en-us/2011/compiler_c/optaps/common/optaps_par_cean_prog.htm

基本的に、次のようなコードを書くことができます。

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命令でベクトル化されます。

于 2012-05-04T06:28:36.803 に答える
2

これは「演算子のオーバーロード」と呼ばれ、Cの機能ではありません。ただし、C++の機能です。C ++がオプションである場合、演算子をオーバーロードする方法に関するチュートリアルがたくさんあります。次の理由でそれを悪と考える人もいます:

  1. コードがコンテキストから外れると、実際に何が起こるかを判断するのは困難です。たとえば、そこに演算子が表示されますが、それらが組み込みの演算子なのか、オーバーロードされた演算子なのかをどうやって知ることができますか?

  2. 演算子をオーバーロードして、一般的ではない意味を適用することができます(これは実際のコードで見たものです)。「/」演算子(除算演算子)をオーバーロードして、のパスセパレーターとして機能させることができます。 OSに依存しない方法でファイル名を処理するクラス:

    Filename f = Filename::MainFileSystem() / "folder1" / "folder2" / "file.txt";
    

    これをしないでください。

オーバーロードされた演算子を使用することにも利点があります。

  1. コードは大幅に簡略化できます。複数の関数呼び出しではなく、次を使用できます

    result = vec1 + vec2 + vec3;
    

    上記のように、コードのその行を見ただけでは、関数が呼び出されるかどうかを判断するのは困難ですが、その難しさが単純化の利点を上回るかどうかは主観的であることに注意してください。

  2. スマートポインタなど、演算子の元のセマンティクスを変更せずに追加機能を提供する、いくつかの気の利いたトリックを実行できます。

于 2012-05-04T02:24:21.277 に答える
1

インライン演算子(V1 + V2)を定義することは可能ですか?

いいえ。ただし、C++です。

于 2012-05-04T00:41:19.680 に答える