2009-11-20 18 views
8

を使用して、ベクターの要素にアクセスする方法通常、私は、次のタイプを使用して3Dベクトルと連携:C - GCC SSEベクトル拡張

なめらかを使用してベクトルを初期化
typedef vec3_t float[3]; 

vec3_t x_basis = {1.0, 0.0, 0.0}; 
vec3_t y_basis = {0.0, 1.0, 0.0}; 
vec3_t z_basis = {0.0, 0.0, 1.0}; 

とし、それらをsmthを使用してアクセスします。 like:

x_basis[X] * y_basis[X] + ... 

私はSSE命令を使用してベクター演算を必要としています。私は次のコードを持っています:

typedef float v4sf __attribute__ ((mode(V4SF))) 
int main(void) 
{ 
    v4sf a,b,c; 
    a = (v4sf){0.1f,0.2f,0.3f,0.4f}; 
    b = (v4sf){0.1f,0.2f,0.3f,0.4f}; 
    c = (v4sf){0.1f,0.2f,0.3f,0.4f}; 
    a = b + c; 
    printf("a=%f \n", a); 
    return 0; 
} 

GCCはこのようにサポートしています。しかし、... まず、私は結果として0.00000を与えます。第二に、私はそのようなベクトルの要素にアクセスすることはできません。 私の質問は:どのように私はそのようなベクトルの要素にアクセスできますか?私はスムーズが必要です。私が使用してこのコードをコンパイルします:

gcc -msse testgcc.c -o testgcc 
+0

質問はそれほど難しくありませんでした。自分自身をgccの専門家とはみなしません。次回より無害なタイトルを使用して、私はほとんど質問をスキップしました。 – hirschhornsalz

答えて

16

要素にアクセスするための安全かつ推奨される方法ではなく、コンパイラのエイリアシング検出機構を愚か者と不安定なコードにつながる可能性がポインタ型punningの、組合です。

union Vec4 { 
    v4sf v; 
    float e[4]; 
}; 

Vec4 vec; 
vec.v = (v4sf){0.1f,0.2f,0.3f,0.4f}; 
printf("%f %f %f %f\n", vec.e[0], vec.e[1], vec.e[2], vec.e[3]); 

+1

いいえ、elder_georgeはより実用的な例を示しています。マクロやインラインでアドバイスを実装すれば十分です。 – psihodelia

+2

十分分かりにくいようです。タイプ・ペーンド・ポインタを参照解除すると、厳密なエイリアシング・ルールが破損するため、ポインタによるタイプ・ペニングは悪いことです。この結果、未定義の動作が発生します。インライン化やマクロ化では安全ではありません。しかし、コンパイラオプション_-fno-strict-aliasing_を使うことができます。これは、このような壊れたコードのために作られています。結果のバイナリは、コンパイラに最適化を拒否するため、いくぶん遅くなる可能性があります。そのことと、それがgcc.gnu.org/onlinedocs/gcc/... "-fstrict-aliasing"の下で悪い理由を読んでください。 – hirschhornsalz

+1

はい、@drhirshが正しいです。@ psihodeliaで提供されているサンプルでは私のソリューションが動作しますが、アラインメントが崩れて小さな変更があっても失敗します。 –

5

あなたはあなたのようにaを再解釈する必要があることを忘れている[0] Xの要素にアクセスするには、[1] Yの要素にアクセスするには、など

PSのような浮動小数点数の配列。コード正常に動作し、以下:この質問への感謝:

int main(){ 
    v4sf a,b,c; 
    a = (v4sf){0.1f,0.2f,0.3f,0.4f}; 
    b = (v4sf){0.1f,0.2f,0.3f,0.4f}; 
    c = (v4sf){0.1f,0.2f,0.3f,0.4f}; 
    a = b + c; 
    float* pA = (float*) &a; 
    printf("a=[%f %f %f %f]\n",pA[0], pA[1], pA[2], pA[3]); 
    return 0; 
} 

P.S、私はgccが、このようなSSEをサポートしていることを知りませんでした。

UPDATE:配列が一度整列しないと、この解決策は失敗します。 @drhirshによって提供されるソリューションには、この問題はありません。

+0

omg ありがとうございます! – psihodelia

+4

種類の間違いは危険です。 – hirschhornsalz

6

なお、今、GCC 4.6 supports添字ベクトル:Cベクターで

がベクトル要素と基本型の同じ数の配列であったかのように添字することができます。範囲外のアクセスは、実行時に未定義の動作を呼び出します。ベクタサブスクリプションのアウトオブバウンドアクセスの警告は、-Warray-boundsを使用して有効にすることができます。

+1

これはCではなくC++でのみ動作します。未解決のバグがあります:http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51033 –

+1

@DavidGivenこれは修正済みとマークされました。 –