2016-05-07 5 views
1

AVX/SSEを使用して浮動小数点数を切り捨て、整数のベクトルを生成する方法はありますか?すべてのフロア固有のメソッドは浮動小数点の最終ベクトルを生成するように見えますが、丸めは整数を生成するので奇数です。AVX/SSEラウンドが浮動小数点を返し、intsのベクトルを返しますか?

+0

整数への変換は何とか丸めたり切り捨てたりする必要がありますが、FP値を変換せずに最も近い整数に丸めることができます。 (['float nearbyintf(float x)'](http://en.cppreference.com/w/c/numeric/math/nearbyint)を参照してください) –

答えて

1

変換命令を使用:


int _mm_cvt_ss2si (__m128 a) 

は、整数を整数で返すaの下位32ビット浮動小数点コンポーネントを変換します。 aの上位3つのコンポーネントは無視されます。


__m128i _mm_cvtps_epi32 (__m128 a); 

すべての4つの32ビット整数と4 32ビット整数の戻りベクトルに浮かぶ変換します。


頻繁に使用されるものです。コンバージョンを処理するにはadditional variationsがあります。

+4

OPは切り捨てられた結果を望んでいます。 -Infではなく0に向かっていると仮定すると、 '_mm_cvttps_epi32'は理想的な命令の組み込みです。 -Infに丸めるには、 'roundps'が必要です。あるいは、デフォルトの丸めモードを一時的に変更することもできます。 –

+0

@PeterCordes私はあなたが何を意味するのか分かりませんが、もし私が4.9を持っていれば私は4を望んでいます。もし100.3434があれば私は100を望んでいますか? – mezamorphic

+2

@mezamorphic: '-4.9'をお持ちの場合、' -5'(床)または '-4'(切り詰め)しますか? –

1

簡単な方法は、このROUNDPS命令を使用して、その後、整数符号付きダブルfloat秒を変換するCVTPS2DQ命令を適用することになります。 AVX YMMベクトルの場合

; xmm0 is assumed to be packed float input vector 
roundps xmm0, xmm0, 3 ; truncate mode, see below as requested in comment on the other answer 
cvtps2dq xmm0, xmm0 
; xmm0 now contains the (rounded) packed integer vector 

「V」との指示をプレフィックスとYMM年代にXMM年代を変更します。コードは次のようになります。

ROUNDPSはXMM2/M128でこの

ラウンドパック単精度浮動小数点値と同じように動作し、結果をxmm1に置きます。丸めモードはimm8によって決定されます。

丸めモード(即時/第三のオペランド)は、次の値を有することができる(現在のインテルドキュメントのテーブル4-15 - Rounding Modes and Encoding of Rounding Control (RC) Fieldから採取):

Rounding Mode    RC Field Setting Description 
---------------------------------------------------------- 
Round to nearest (even)  00B    Rounded result is the closest to the infinitely precise result. If two values are equally close, the result is nearest (even) the even value (i.e., the integer value with the least-significant bit of zero). 
Round down (toward −∞)  01B    Rounded result is closest to but no greater than the infinitely precise result. 
Round up (toward +∞)  10B    Rounded result is closest to but no less than the infinitely precise result. 
Round toward 0 (truncate) 11B    Rounded result is closest to but no greater in absolute value than the infinitely precise result. 

可能性の理由を理由の回帰ベクトル丸め演算がfloatであり、intでない場合、次の演算は常に浮動小数点演算(丸められた値)になり、intへの変換は示されているように簡単です。

対応する組み込み関数は、参照されているドキュメントにあります。(Rounding Control (RC) Fieldに依存して)組み込み関数に上記のコードを変換する例がある:ちょうどゼロに最も近い先行する最も近い整数への丸めベクトルのfloat Sに「切り捨て」動作を適用するための

__m128 dst = _mm_cvtps_epi32(_mm_floor_ps(__m128 src)); 

、単一の命令/組み込み関数は十分であろう:

__m128i _mm_cvttps_epi32(__m128 a) 
+3

'roundps'は、-Inf(floor)または+ Inf(ceil)に丸める必要がある場合にのみ必要です。 'cvtps_epi32'はデフォルトの丸めモード(通常は' roundps 00'と同じです)を使いますが、 'cvttps_epi32'は0に切り詰めます。 –

+3

' roundps'が 'int'に変換されない主な理由の一つは' FLT_MAX'が '結果が表現できない可能性があります(インテルが呼び出しているように、範囲外のFP値を変換すると「0x80000000」、「整数不定」の値が得られます)。また、FP番号を整数に変換することなく、時折丸めるのは簡単です。 –

+0

'roundps'のより良い例は、floorまたはceilモードです。これは、デフォルトの丸めモードのcvtまたはcvtt命令では達成できません。 Truncateを行ってからconvert to nearestを行うのは、単一のcvtt命令で行うべきなので、この場合は 'roundps'が何の役に立つのかはわかりません。 –

1

シングル命令OPTIO:固有として

cvttps2dq xmm0, xmm0 

か、をNS:

  • はゼロに向かって切り捨て:最寄りへ__m128i _mm_cvttps_epi32(__m128 a)
  • ラウンド:-INFに向けた__m128i _mm_cvtps_epi32(__m128 a)

2つの命令、SSE4.1 ROUNDPSを使用して、cvtps_epi32

  • ラウンド:__m128 _mm_floor_ps(__m128 s1)
  • ラウンドを+INF:あなたはFP形式のデータを保持したい場合は

__m128 _mm_ceil_ps(__m128 s1)のみ、他の切り捨てやroundpsの最寄りのフォームを使用します。


正数の場合、切り捨てと床は同じです。負の整数の場合はcvtt(-4.9) = -4ですが、floor(-4.9) = -5.0です。 対truncf()を参照してください。


FP値は、Intelが「整数不定」値を呼び出すINT_MININT_MAXの範囲、cvttps and cvtps will give you 0x80000000(すなわちINT_MIN、単に符号ビットセット)、外にある場合。 FP無効例外も発生しますが、FP例外はデフォルトでマスクされます。

関連する問題