2016-10-13 6 views
0

数学的アルゴリズムの実装のヘッダファイルにドットプロダクトを定義する次のマクロコンストラクトがあります。可変次元を持つドットプロダクトのCマクロ

#define DIM 3 
#define MULTIPLY(a, b)  ((a)*(b)) 
#define DOT_PRODUCT(a, b) ( MULTIPLY((a)[0],(b)[0]) + \ 
           MULTIPLY((a)[1],(b)[1]) + \ 
           MULTIPLY((a)[2],(b)[2])) 

おそらく、ディメンションから実装を独立させるために使用されます。しかし明らかに、もし誰かが​​を変更したとしても、それを反映するためにDOT_PRODUCTを修正しなければなりません。

を定義して、設定された寸法​​を自動的に尊重する方法はありますか?おそらく、いくつかの(疑似)再帰的なマクロマジックで?私は何かを考え出そうとしましたが、私のC-fooは特に強くはありません。

+0

私はそうは思いませんが、条件付きロジックを使用して、小さな範囲の「DIM」のすべてのケースを処理できます。 –

+1

関数が実行するマクロは使用しないでください。 – Olaf

+0

あなたは[Boost :: Preprocessor](http://www.boost.org/doc/libs/release/libs/preprocessor/)でそれを行うことができます。そのコードはCまたはC++プリプロセッサ用です。 Boost :: Preprocessorを使ってはいけません。 –

答えて

1

私は@Olafに同意します:機能が使用できるマクロは使用しないでください。 しかし時々状況や欲求がその考えを覆してしまいます。

プリプロセッサは時には正しい場所に適切な数の迂回を望んでいるので、これを得るまで実験しました。私は、私が予測することができなかったことを認めて、少なくとも、面白い、自明ではない部分について、詳しく説明することはできません。

#define DIM 2 
#define CONCAT(x,y,a,b) x ## y(a,b) 
#define DOT_PRODUCT_DIM(y,a,b) CONCAT(DOT_PRODUCT_,y,a,b) 
#define MULTIPLY(a, b)  ((a)*(b)) 
#define DOT_PRODUCT_2(a, b) ( MULTIPLY((a)[0],(b)[0]) + \ 
           MULTIPLY((a)[1],(b)[1])) 
#define DOT_PRODUCT_3(a, b) ( MULTIPLY((a)[0],(b)[0]) + \ 
           MULTIPLY((a)[1],(b)[1]) + \ 
           MULTIPLY((a)[2],(b)[2])) 
#define DOT_PRODUCT_4(a, b) ( MULTIPLY((a)[0],(b)[0]) + \ 
           MULTIPLY((a)[1],(b)[1]) + \ 
           MULTIPLY((a)[2],(b)[2]) + \ 
           MULTIPLY((a)[3],(b)[3])) 
#define DOT_PRODUCT(a,b) DOT_PRODUCT_DIM(DIM,a,b) 

DOT_PRODUCT_DIM(2,a,b) 
DOT_PRODUCT_DIM(3,a,b) 
DOT_PRODUCT_DIM(4,a,b) 
DOT_PRODUCT_DIM(DIM,a,b) 
DOT_PRODUCT(a,b) 

OUTPUT(gcc -E Toy.c)のみ#define DIM 4を変更した後

((((a)[0])*((b)[0])) + (((a)[1])*((b)[1])) + (((a)[2])*((b)[2]))) 
((((a)[0])*((b)[0])) + (((a)[1])*((b)[1])) + (((a)[2])*((b)[2]))) 

OUTPUT((出力の最後の2行を引用のみ#define DIM 3を変更した後、)

((((a)[0])*((b)[0])) + (((a)[1])*((b)[1]))) 
((((a)[0])*((b)[0])) + (((a)[1])*((b)[1])) + (((a)[2])*((b)[2]))) 
((((a)[0])*((b)[0])) + (((a)[1])*((b)[1])) + (((a)[2])*((b)[2])) + (((a)[3])*((b)[3]))) 
((((a)[0])*((b)[0])) + (((a)[1])*((b)[1]))) 
((((a)[0])*((b)[0])) + (((a)[1])*((b)[1]))) 

OUTPUT出力の最後の2行のみを引用する):

((((a)[0])*((b)[0])) + (((a)[1])*((b)[1])) + (((a)[2])*((b)[2])) + (((a)[3])*((b)[3]))) 
((((a)[0])*((b)[0])) + (((a)[1])*((b)[1])) + (((a)[2])*((b)[2])) + (((a)[3])*((b)[3]))) 

(出力のみの最後の2行引用のみ#define DIM 5を変更した後、)OUTPUT:もちろん

DOT_PRODUCT_5(a,b) 
DOT_PRODUCT_5(a,b) 

、定義されなければならないDOT_PRODUCT_number()中間マクロを。私が提供した例は仕事であり、体系的な問題はなく、より高い次元を妨げることになります。
ユースケースに一致することを願っています。あなたは不確定な、静的に未知/予測不可能な多数の次元を考えていませんか?

+0

興味深い解決策、これは私の使用例をカバーするでしょう。 DIMを変更することで2Dと3Dを同じように扱えるようにするための変形が本当に必要です。原因の理想的な解決策は完全に柔軟性がありますが、これは有用ですが、ありがとうございます。 IF-ELSEIF-ELSE構成では、1つの質問だけで同様のことが達成できないことがありますか? – PeterE

+0

私はちょうどDIMを切り替えるだけの必要性に訴えていると思った。それはあなたにとってうまくいかないのですか?私の3つの例は、2,3,4(、5)を通してDIMを切り替えるだけで適切な結果が得られることを示しています。 IF-ELSEIF構成も可能です。しかし、私は(無意識にも意識的にも)@ジョン・コールマンに挑戦していました。彼のコメントは、彼がそれを唯一の方法と考えたように聞こえました。また、私の解決策は、明示的にディメンション化された 'DOT_PRODUCT_digit()'バージョンへの(DIM制御のデフォルトに加えて)アクセスを提供します。たとえば、ほとんどの場合は3dimを実行しますが、4dimの場合はいくつかあります。 – Yunnosch

+0

私はあなたが私のコメントを誤解したと思う、あなたのソリューション**は**私はDIM = 2またはDIM = 3が必要なので**私のために働く。しかし、その場合はIF-ELSEがおそらくもっと簡単でしょう。当初、私は任意のDIMを処理できる完璧なソリューションを探していましたが、それは私の問題を解決するために本当に必要なものです。 – PeterE

関連する問題