_mm_extract_ps sse gcc instrinc関数を使用して、c/c ++のフロートにhexフロートをフロートに変換する方法
-
01-10-2019 - |
質問
SSEコードを2D畳み込みに書いていますが、SSEドキュメントは非常にまばらです。 _mm_dp_psでドット製品を計算し、_mm_extract_psを使用してドット製品の結果を取得しますが、_mm_extract_psはフロートを表す16進数を返し、この16進フロートを通常のフロートに変換する方法を見つけ出すことができません。フロートを返す__builtin_ia32_vec_ext_v4sfを使用できますが、他のコンパイラと互換性を維持したいと思います。
_mm_extract_ps (__m128 __X, const int __N)
{
union { int i; float f; } __tmp;
__tmp.f = __builtin_ia32_vec_ext_v4sf ((__v4sf)__X, __N);
return __tmp.i;
}
私はどのようなポイントが欠けていますか?
少し助けてくれてありがとう。
opensuse 11.2
GCC 4.4.1
C ++
コンパイラオプション
-fopenmp -wall -o3 -msse4.1 -march = core2
リンカーオプション
-LGOMP -WALL -O3 -MSSE4.1 -MARCH = CORE2
解決
使用できるはずです _MM_EXTRACT_FLOAT
.
ちなみに、それはまるで私には見えます _mm_extract_ps
と _MM_EXTRACT_FLOAT
逆であるべきです、すなわち _mm_extract_ps
フロートを返す必要があります _MM_EXTRACT_FLOAT
INT表現を返す必要がありますが、何を知っていますか。
他のヒント
_mm_cvtss_f32(_mm_shuffle_ps(__X, __X, __N))
仕事をします。
そして、これまでに言及されているすべてを例示するために:
main.c
#include <assert.h>
#include <x86intrin.h>
int main(void) {
/* 32-bit. */
{
__m128 x = _mm_set_ps(1.5f, 2.5f, 3.5f, 4.5f);
/* _MM_EXTRACT_FLOAT */
float f;
_MM_EXTRACT_FLOAT(f, x, 3);
assert(f == 1.5f);
_MM_EXTRACT_FLOAT(f, x, 2);
assert(f == 2.5f);
_MM_EXTRACT_FLOAT(f, x, 1);
assert(f == 3.5f);
_MM_EXTRACT_FLOAT(f, x, 0);
assert(f == 4.5f);
/* _mm_cvtss_f32 + _mm_shuffle_ps */
assert(_mm_cvtss_f32(x) == 4.5f);
assert(_mm_cvtss_f32(_mm_shuffle_ps(x, x, 1)) == 3.5f);
assert(_mm_cvtss_f32(_mm_shuffle_ps(x, x, 2)) == 2.5f);
assert(_mm_cvtss_f32(_mm_shuffle_ps(x, x, 3)) == 1.5f);
}
/* 64-bit. */
{
__m128d x = _mm_set_pd(1.5, 2.5);
/* _mm_cvtsd_f64 + _mm_unpackhi_pd */
assert(_mm_cvtsd_f64(x) == 2.5);
assert(_mm_cvtsd_f64(_mm_unpackhi_pd(x, x)) == 1.5);
}
}
コンパイルと実行:
gcc -ggdb3 -O0 -std=c99 -Wall -Wextra -pedantic -o main.out main.c
./main.out
上記のダブル: _mm_cvtsd_f64高次の浮動小数点のためのアナゴン
Ubuntu 19.04 AMD64でテスト。
extern void _mm_store_ss(float*、__m128);
「xmmintrin.h」を参照してください。