静态方法:数学运算

每种数据类型都有一系列运算符,支持基本的数学运算。

SIMD.%type%.abs(),SIMD.%type%.neg()

abs方法接受一个 SIMD 值作为参数,将它的每个通道都转成绝对值,作为一个新的 SIMD 值返回。

  1. var a = SIMD.Float32x4(-1, -2, 0, NaN);
  2. SIMD.Float32x4.abs(a)
  3. // Float32x4[1, 2, 0, NaN]

neg方法接受一个 SIMD 值作为参数,将它的每个通道都转成负值,作为一个新的 SIMD 值返回。

  1. var a = SIMD.Float32x4(-1, -2, 3, 0);
  2. SIMD.Float32x4.neg(a)
  3. // Float32x4[1, 2, -3, -0]
  4. var b = SIMD.Float64x2(NaN, Infinity);
  5. SIMD.Float64x2.neg(b)
  6. // Float64x2[NaN, -Infinity]

SIMD.%type%.add(),SIMD.%type%.addSaturate()

add方法接受两个 SIMD 值作为参数,将它们的每个通道相加,作为一个新的 SIMD 值返回。

  1. var a = SIMD.Float32x4(1.0, 2.0, 3.0, 4.0);
  2. var b = SIMD.Float32x4(5.0, 10.0, 15.0, 20.0);
  3. var c = SIMD.Float32x4.add(a, b);

上面代码中,经过加法运算,新的 SIMD 值为(6.0, 12.0, 18.0. 24.0)

addSaturate方法跟add方法的作用相同,都是两个通道相加,但是溢出的处理不一致。对于add方法,如果两个值相加发生溢出,溢出的二进制位会被丢弃; addSaturate方法则是返回该数据类型的最大值。

  1. var a = SIMD.Uint16x8(65533, 65534, 65535, 65535, 1, 1, 1, 1);
  2. var b = SIMD.Uint16x8(1, 1, 1, 5000, 1, 1, 1, 1);
  3. SIMD.Uint16x8.addSaturate(a, b);
  4. // Uint16x8[65534, 65535, 65535, 65535, 2, 2, 2, 2]
  5. var c = SIMD.Int16x8(32765, 32766, 32767, 32767, 1, 1, 1, 1);
  6. var d = SIMD.Int16x8(1, 1, 1, 5000, 1, 1, 1, 1);
  7. SIMD.Int16x8.addSaturate(c, d);
  8. // Int16x8[32766, 32767, 32767, 32767, 2, 2, 2, 2]

上面代码中,Uint16的最大值是 65535,Int16的最大值是 32767。一旦发生溢出,就返回这两个值。

注意,Uint32x4Int32x4这两种数据类型没有addSaturate方法。

SIMD.%type%.sub(),SIMD.%type%.subSaturate()

sub方法接受两个 SIMD 值作为参数,将它们的每个通道相减,作为一个新的 SIMD 值返回。

  1. var a = SIMD.Float32x4(-1, -2, 3, 4);
  2. var b = SIMD.Float32x4(3, 3, 3, 3);
  3. SIMD.Float32x4.sub(a, b)
  4. // Float32x4[-4, -5, 0, 1]

subSaturate方法跟sub方法的作用相同,都是两个通道相减,但是溢出的处理不一致。对于sub方法,如果两个值相减发生溢出,溢出的二进制位会被丢弃; subSaturate方法则是返回该数据类型的最小值。

  1. var a = SIMD.Uint16x8(5, 1, 1, 1, 1, 1, 1, 1);
  2. var b = SIMD.Uint16x8(10, 1, 1, 1, 1, 1, 1, 1);
  3. SIMD.Uint16x8.subSaturate(a, b)
  4. // Uint16x8[0, 0, 0, 0, 0, 0, 0, 0]
  5. var c = SIMD.Int16x8(-100, 0, 0, 0, 0, 0, 0, 0);
  6. var d = SIMD.Int16x8(32767, 0, 0, 0, 0, 0, 0, 0);
  7. SIMD.Int16x8.subSaturate(c, d)
  8. // Int16x8[-32768, 0, 0, 0, 0, 0, 0, 0, 0]

上面代码中,Uint16的最小值是0Int16的最小值是-32678。一旦运算发生溢出,就返回最小值。

SIMD.%type%.mul(),SIMD.%type%.div(),SIMD.%type%.sqrt()

mul方法接受两个 SIMD 值作为参数,将它们的每个通道相乘,作为一个新的 SIMD 值返回。

  1. var a = SIMD.Float32x4(-1, -2, 3, 4);
  2. var b = SIMD.Float32x4(3, 3, 3, 3);
  3. SIMD.Float32x4.mul(a, b)
  4. // Float32x4[-3, -6, 9, 12]

div方法接受两个 SIMD 值作为参数,将它们的每个通道相除,作为一个新的 SIMD 值返回。

  1. var a = SIMD.Float32x4(2, 2, 2, 2);
  2. var b = SIMD.Float32x4(4, 4, 4, 4);
  3. SIMD.Float32x4.div(a, b)
  4. // Float32x4[0.5, 0.5, 0.5, 0.5]

sqrt方法接受一个 SIMD 值作为参数,求出每个通道的平方根,作为一个新的 SIMD 值返回。

  1. var b = SIMD.Float64x2(4, 8);
  2. SIMD.Float64x2.sqrt(b)
  3. // Float64x2[2, 2.8284271247461903]

SIMD.%FloatType%.reciprocalApproximation(),SIMD.%type%.reciprocalSqrtApproximation()

reciprocalApproximation方法接受一个 SIMD 值作为参数,求出每个通道的倒数(1 / x),作为一个新的 SIMD 值返回。

  1. var a = SIMD.Float32x4(1, 2, 3, 4);
  2. SIMD.Float32x4.reciprocalApproximation(a);
  3. // Float32x4[1, 0.5, 0.3333333432674408, 0.25]

reciprocalSqrtApproximation方法接受一个 SIMD 值作为参数,求出每个通道的平方根的倒数(1 / (x^0.5)),作为一个新的 SIMD 值返回。

  1. var a = SIMD.Float32x4(1, 2, 3, 4);
  2. SIMD.Float32x4.reciprocalSqrtApproximation(a)
  3. // Float32x4[1, 0.7071067690849304, 0.5773502588272095, 0.5]

注意,只有浮点数的数据类型才有这两个方法。

SIMD.%IntegerType%.shiftLeftByScalar()

shiftLeftByScalar方法接受一个 SIMD 值作为参数,然后将每个通道的值左移指定的位数,作为一个新的 SIMD 值返回。

  1. var a = SIMD.Int32x4(1, 2, 4, 8);
  2. SIMD.Int32x4.shiftLeftByScalar(a, 1);
  3. // Int32x4[2, 4, 8, 16]

如果左移后,新的值超出了当前数据类型的位数,溢出的部分会被丢弃。

  1. var ix4 = SIMD.Int32x4(1, 2, 3, 4);
  2. var jx4 = SIMD.Int32x4.shiftLeftByScalar(ix4, 32);
  3. // Int32x4[0, 0, 0, 0]

注意,只有整数的数据类型才有这个方法。

SIMD.%IntegerType%.shiftRightByScalar()

shiftRightByScalar方法接受一个 SIMD 值作为参数,然后将每个通道的值右移指定的位数,返回一个新的 SIMD 值。

  1. var a = SIMD.Int32x4(1, 2, 4, -8);
  2. SIMD.Int32x4.shiftRightByScalar(a, 1);
  3. // Int32x4[0, 1, 2, -4]

如果原来通道的值是带符号的值,则符号位保持不变,不受右移影响。如果是不带符号位的值,则右移后头部会补0

  1. var a = SIMD.Uint32x4(1, 2, 4, -8);
  2. SIMD.Uint32x4.shiftRightByScalar(a, 1);
  3. // Uint32x4[0, 1, 2, 2147483644]

上面代码中,-8右移一位变成了2147483644,是因为对于 32 位无符号整数来说,-8的二进制形式是11111111111111111111111111111000,右移一位就变成了01111111111111111111111111111100,相当于2147483644

注意,只有整数的数据类型才有这个方法。