単精度データの配列を、余分なバイトを処理するために配列が適切なサイズになっていることを使用して、倍精度にプロモートするルーチンがあります。
void dpromote(const int n, double *x)
{
for (int i = n; i --> 0 ;) {
x[i] = ((float *)x)[i];
}
}
入口にx
はn
float
sが含まれ、出口にはn
double
sが含まれます。
void test_dpromote()
{
double e[] = {1, 2, 3, 4, 5, 6, 7};
float x[] = {1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0};
const int n = sizeof(e)/sizeof(e[0]);
dpromote(n, (void *) x);
/* memcmp(x, e, sizeof(e)) will return 0 when this works as expected */
}
なぜ私はこれをしているのですか?数値が多いコード内の混合精度の反復的な改良。この質問の目的のために、あなたはその理由を本当に無関係であるとして無視することができます。
複数のコンパイラはdpromote
、厳密なエイリアシングが有効になっているさまざまな積極的な最適化レベルのロジックで問題ありません。最近、あるコンパイラベンダー(名前は不明のまま)は、ループのインデックスを再作成して、後方トラバーサルではなく、メモリを介した前方トラバーサルになるようにすることを決定しました。コードを30分見つめると、ループ変換によってまったくのゴミが発生することがわかります。
すべてのC99厳密なエイリアスのベルとホイッスルが有効になっているdpromote
ロジックは、未定義の動作に依存していますか?コードが未定義のことをしていない限り、コンパイラがループのインデックスを変更しても問題ないと考える理由がわかりません。