LoginSignup
1
1

More than 5 years have passed since last update.

vfixupimmps

Last updated at Posted at 2014-12-05

浮動小数値の種類に対応する変換ができます。

区別できる種類は、

  • qNaN
  • sNaN
  • zero
  • +1.0
  • -inf
  • +inf
  • 負数
  • 正数

の7個です。これがsrc2で指定されます。

どういう変換をするかを、src3 で決めます変換の種類は、16種類で、4bitで識別できるので、8種類の値を32bit値のテーブル引きで求めます

  • qNaN -> 0-3bit
  • sNaN -> 4-7bit
  • zero -> 8-11bit
  • +1.0 -> 12->15bit
  • -inf -> 16->19bit
  • +inf -> 20->23bit
  • 負数 -> 24->27bit
  • 正数 -> 28->31bit

この選んだ4bitで、結果が決まります。

以下Intel(R) Architecture Instruction Set Extensions Programming Reference(https://software.intel.com/en-us/intel-architecture-instruction-set-extensions-programming-reference ) からコピペ。

  • 0000: dest[31:0] = dest[31:0]; ; preserve content of DEST
  • 0001: dest[31:0] = tsrc[31:0]; ; pass through src1 normal input value, denormal as zero
  • 0010: dest[31:0] = QNaN(tsrc[31:0]);
  • 0011: dest[31:0] = QNAN_Indefinite;
  • 0100: dest[31:0] = -INF;
  • 0101: dest[31:0] = +INF;
  • 0110: dest[31:0] = tsrc.sign? –INF : +INF;
  • 0111: dest[31:0] = -0;
  • 1000: dest[31:0] = +0;
  • 1001: dest[31:0] = -1;
  • 1010: dest[31:0] = +1;
  • 1011: dest[31:0] = 1⁄2;
  • 1100: dest[31:0] = 90.0;
  • 1101: dest[31:0] = PI/2;
  • 1110: dest[31:0] = MAX_FLOAT;
  • 1111: dest[31:0] = -MAX_FLOAT;

#include <immintrin.h>
#include <stdio.h>
#include <math.h>

float data1[16] = {100.0f,
                   200.0f,
                   300.0f,
                   400.0f,
                   500.0f};

float data2[16] = {0, -0, 1, -1};
#define GEN_ENTRY(a,b,c,d, e,f,g,h)                     \
    (((a)<<0) | ((b)<<4) | ((c)<<8) | ((d)<<12) |        \
     ((e)<<16) | ((f)<<20) | ((g)<<24) | ((h)<<28))

int data3[16] = {
    GEN_ENTRY(0,                /* qnan */
              1,                /* snan */
              14,               /* zero */
              15,               /* 1.0 */
              4,                /* -inf */
              5,                /* +inf */
              13,               /* -val */
              12),              /* +val */
};

float data4[16];

float
test(float v)
{
    __m512 a = _mm512_loadu_ps(data1);
    __m512 b = _mm512_set1_ps(v);
    __m512i c = _mm512_loadu_si512(data3);
    __m512 out;

    out = _mm512_fixupimm_ps(a, b, c, 7);
    _mm512_storeu_ps(data4, out);
    printf("%10f -> %8.4f\n", v, data4[0]);
}

int
main()
{
    test(+1.0f);
    test(+2.0f);
    test(-1.0f);
    test(-2.0f);
    test(+0.0f);
    test(-0.0f);

    test(1.0f/0.0f);

    test(-nanf(""));
    test(+nanf(""));
    test(-nanf(""));
    test(+nanf(""));
}
$ ./sde -- ./a.out
  1.000000 -> -340282346638528859811704183484516925440.0000
  2.000000 ->  90.0000
 -1.000000 ->   1.5708
 -2.000000 ->   1.5708
  0.000000 -> 340282346638528859811704183484516925440.0000
 -0.000000 -> 340282346638528859811704183484516925440.0000
       inf ->      inf
      -nan -> 100.0000
       nan -> 100.0000
      -nan -> 100.0000
       nan -> 100.0000

明日は @tanakmura が vpternlogd について書きます。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1