--- a/js/src/builtin/SIMD.cpp
+++ b/js/src/builtin/SIMD.cpp
@@ -966,63 +966,70 @@ FuncWith(JSContext *cx, unsigned argc, V
for (unsigned i = 0; i < V::lanes; i++)
result[i] = OpWith<Elem>::apply(i, withAsBool, val[i]);
}
return StoreResult<V>(cx, args, result);
}
template<typename V>
static bool
-FuncShuffle(JSContext *cx, unsigned argc, Value *vp)
+Swizzle(JSContext *cx, unsigned argc, Value *vp)
{
typedef typename V::Elem Elem;
CallArgs args = CallArgsFromVp(argc, vp);
- if (args.length() != 2 && args.length() != 3)
+ if (args.length() != (V::lanes + 1) || !IsVectorObject<V>(args[0]))
return ErrorBadArgs(cx);
- // Let L be V::Lanes. Each lane can contain L lanes, so the log2(L) first
- // bits select the first lane, the next log2(L) the second, and so on.
- const uint32_t SELECT_SHIFT = FloorLog2(V::lanes);
- const uint32_t SELECT_MASK = V::lanes - 1;
- const int32_t MAX_MASK_VALUE = int32_t(pow(double(V::lanes), double(V::lanes))) - 1;
- MOZ_ASSERT(MAX_MASK_VALUE > 0);
+ int32_t lanes[V::lanes];
+ for (unsigned i = 0; i < V::lanes; i++) {
+ int32_t lane = -1;
+ if (!ToInt32(cx, args[i + 1], &lane))
+ return false;
+ if (lane < 0 || lane >= V::lanes)
+ return ErrorBadArgs(cx);
+ lanes[i] = lane;
+ }
+
+ Elem *val = TypedObjectMemory<Elem *>(args[0]);
Elem result[V::lanes];
- if (args.length() == 2) {
- if (!IsVectorObject<V>(args[0]) || !args[1].isInt32())
- return ErrorBadArgs(cx);
+ for (unsigned i = 0; i < V::lanes; i++)
+ result[i] = val[lanes[i]];
+
+ return StoreResult<V>(cx, args, result);
+}
- Elem *val = TypedObjectMemory<Elem *>(args[0]);
- int32_t maskArg;
- if (!ToInt32(cx, args[1], &maskArg))
- return false;
- if (maskArg < 0 || maskArg > MAX_MASK_VALUE)
- return ErrorBadArgs(cx);
+template<typename V>
+static bool
+Shuffle(JSContext *cx, unsigned argc, Value *vp)
+{
+ typedef typename V::Elem Elem;
+
+ CallArgs args = CallArgsFromVp(argc, vp);
+ if (args.length() != (V::lanes + 2) || !IsVectorObject<V>(args[0]) || !IsVectorObject<V>(args[1]))
+ return ErrorBadArgs(cx);
- for (unsigned i = 0; i < V::lanes; i++)
- result[i] = val[(maskArg >> (i * SELECT_SHIFT)) & SELECT_MASK];
- } else {
- MOZ_ASSERT(args.length() == 3);
- if (!IsVectorObject<V>(args[0]) || !IsVectorObject<V>(args[1]) || !args[2].isInt32())
+ int32_t lanes[V::lanes];
+ for (unsigned i = 0; i < V::lanes; i++) {
+ int32_t lane = -1;
+ if (!ToInt32(cx, args[i + 2], &lane))
+ return false;
+ if (lane < 0 || lane >= (2 * V::lanes))
return ErrorBadArgs(cx);
+ lanes[i] = lane;
+ }
- Elem *val1 = TypedObjectMemory<Elem *>(args[0]);
- Elem *val2 = TypedObjectMemory<Elem *>(args[1]);
- int32_t maskArg;
- if (!ToInt32(cx, args[2], &maskArg))
- return false;
- if (maskArg < 0 || maskArg > MAX_MASK_VALUE)
- return ErrorBadArgs(cx);
+ Elem *lhs = TypedObjectMemory<Elem *>(args[0]);
+ Elem *rhs = TypedObjectMemory<Elem *>(args[1]);
- unsigned i = 0;
- for (; i < V::lanes / 2; i++)
- result[i] = val1[(maskArg >> (i * SELECT_SHIFT)) & SELECT_MASK];
- for (; i < V::lanes; i++)
- result[i] = val2[(maskArg >> (i * SELECT_SHIFT)) & SELECT_MASK];
+ Elem result[V::lanes];
+ for (unsigned i = 0; i < V::lanes; i++) {
+ Elem *selectedInput = lanes[i] < V::lanes ? lhs : rhs;
+ result[i] = selectedInput[lanes[i] % V::lanes];
}
return StoreResult<V>(cx, args, result);
}
template<typename Op>
static bool
Int32x4BinaryScalar(JSContext *cx, unsigned argc, Value *vp)
--- a/js/src/builtin/SIMD.h
+++ b/js/src/builtin/SIMD.h
@@ -40,36 +40,39 @@
V(greaterThan, (BinaryFunc<Float32x4, GreaterThan, Int32x4>), 2, 0) \
V(greaterThanOrEqual, (BinaryFunc<Float32x4, GreaterThanOrEqual, Int32x4>), 2, 0) \
V(lessThan, (BinaryFunc<Float32x4, LessThan, Int32x4>), 2, 0) \
V(lessThanOrEqual, (BinaryFunc<Float32x4, LessThanOrEqual, Int32x4>), 2, 0) \
V(max, (BinaryFunc<Float32x4, Maximum, Float32x4>), 2, 0) \
V(min, (BinaryFunc<Float32x4, Minimum, Float32x4>), 2, 0) \
V(mul, (BinaryFunc<Float32x4, Mul, Float32x4>), 2, 0) \
V(notEqual, (BinaryFunc<Float32x4, NotEqual, Int32x4>), 2, 0) \
- V(shuffle, FuncShuffle<Float32x4>, 2, 0) \
V(or, (CoercedBinaryFunc<Float32x4, Int32x4, Or, Float32x4>), 2, 0) \
V(scale, (FuncWith<Float32x4, Scale>), 2, 0) \
V(sub, (BinaryFunc<Float32x4, Sub, Float32x4>), 2, 0) \
V(withX, (FuncWith<Float32x4, WithX>), 2, 0) \
V(withY, (FuncWith<Float32x4, WithY>), 2, 0) \
V(withZ, (FuncWith<Float32x4, WithZ>), 2, 0) \
V(withW, (FuncWith<Float32x4, WithW>), 2, 0) \
V(xor, (CoercedBinaryFunc<Float32x4, Int32x4, Xor, Float32x4>), 2, 0)
#define FLOAT32X4_TERNARY_FUNCTION_LIST(V) \
V(clamp, Float32x4Clamp, 3, 0) \
- V(select, Float32x4Select, 3, 0) \
- V(shuffleMix, FuncShuffle<Float32x4>, 3, 0)
+ V(select, Float32x4Select, 3, 0)
+
+#define FLOAT32X4_SHUFFLE_FUNCTION_LIST(V) \
+ V(swizzle, Swizzle<Float32x4>, 2, 0) \
+ V(shuffle, Shuffle<Float32x4>, 3, 0)
#define FLOAT32X4_FUNCTION_LIST(V) \
FLOAT32X4_NULLARY_FUNCTION_LIST(V) \
FLOAT32X4_UNARY_FUNCTION_LIST(V) \
FLOAT32X4_BINARY_FUNCTION_LIST(V) \
- FLOAT32X4_TERNARY_FUNCTION_LIST(V)
+ FLOAT32X4_TERNARY_FUNCTION_LIST(V) \
+ FLOAT32X4_SHUFFLE_FUNCTION_LIST(V)
#define INT32X4_NULLARY_FUNCTION_LIST(V) \
V(zero, (FuncZero<Int32x4>), 0, 0)
#define INT32X4_UNARY_FUNCTION_LIST(V) \
V(fromFloat32x4, (FuncConvert<Float32x4, Int32x4>), 1, 0) \
V(fromFloat32x4Bits, (FuncConvertBits<Float32x4, Int32x4>), 1, 0) \
V(neg, (UnaryFunc<Int32x4, Neg, Int32x4>), 1, 0) \
@@ -83,40 +86,43 @@
V(greaterThan, (BinaryFunc<Int32x4, GreaterThan, Int32x4>), 2, 0) \
V(lessThan, (BinaryFunc<Int32x4, LessThan, Int32x4>), 2, 0) \
V(mul, (BinaryFunc<Int32x4, Mul, Int32x4>), 2, 0) \
V(or, (BinaryFunc<Int32x4, Or, Int32x4>), 2, 0) \
V(sub, (BinaryFunc<Int32x4, Sub, Int32x4>), 2, 0) \
V(shiftLeft, (Int32x4BinaryScalar<ShiftLeft>), 2, 0) \
V(shiftRight, (Int32x4BinaryScalar<ShiftRight>), 2, 0) \
V(shiftRightLogical, (Int32x4BinaryScalar<ShiftRightLogical>), 2, 0) \
- V(shuffle, FuncShuffle<Int32x4>, 2, 0) \
V(withFlagX, (FuncWith<Int32x4, WithFlagX>), 2, 0) \
V(withFlagY, (FuncWith<Int32x4, WithFlagY>), 2, 0) \
V(withFlagZ, (FuncWith<Int32x4, WithFlagZ>), 2, 0) \
V(withFlagW, (FuncWith<Int32x4, WithFlagW>), 2, 0) \
V(withX, (FuncWith<Int32x4, WithX>), 2, 0) \
V(withY, (FuncWith<Int32x4, WithY>), 2, 0) \
V(withZ, (FuncWith<Int32x4, WithZ>), 2, 0) \
V(withW, (FuncWith<Int32x4, WithW>), 2, 0) \
V(xor, (BinaryFunc<Int32x4, Xor, Int32x4>), 2, 0)
#define INT32X4_TERNARY_FUNCTION_LIST(V) \
V(select, Int32x4Select, 3, 0) \
- V(shuffleMix, FuncShuffle<Int32x4>, 3, 0)
#define INT32X4_QUARTERNARY_FUNCTION_LIST(V) \
V(bool, Int32x4Bool, 4, 0)
+#define INT32X4_SHUFFLE_FUNCTION_LIST(V) \
+ V(swizzle, Swizzle<Int32x4>, 2, 0) \
+ V(shuffle, Shuffle<Int32x4>, 3, 0)
+
#define INT32X4_FUNCTION_LIST(V) \
INT32X4_NULLARY_FUNCTION_LIST(V) \
INT32X4_UNARY_FUNCTION_LIST(V) \
INT32X4_BINARY_FUNCTION_LIST(V) \
INT32X4_TERNARY_FUNCTION_LIST(V) \
- INT32X4_QUARTERNARY_FUNCTION_LIST(V)
+ INT32X4_QUARTERNARY_FUNCTION_LIST(V) \
+ INT32X4_SHUFFLE_FUNCTION_LIST(V)
#define FOREACH_INT32X4_SIMD_OP(_) \
_(fromFloat32x4) \
_(fromFloat32x4Bits) \
_(shiftLeft) \
_(shiftRight) \
_(shiftRightLogical)
#define FOREACH_FLOAT32X4_SIMD_OP(_) \
--- a/js/src/js.msg
+++ b/js/src/js.msg
@@ -416,17 +416,17 @@ MSG_DEF(JSMSG_TYPEDOBJECT_ARRAYTYPE_BAD_
MSG_DEF(JSMSG_TYPEDOBJECT_BAD_ARGS, 0, JSEXN_TYPEERR, "invalid arguments")
MSG_DEF(JSMSG_TYPEDOBJECT_BINARYARRAY_BAD_INDEX, 0, JSEXN_RANGEERR, "invalid or out-of-range index")
MSG_DEF(JSMSG_TYPEDOBJECT_HANDLE_UNATTACHED, 0, JSEXN_TYPEERR, "handle unattached")
MSG_DEF(JSMSG_TYPEDOBJECT_STRUCTTYPE_BAD_ARGS, 0, JSEXN_RANGEERR, "invalid field descriptor")
MSG_DEF(JSMSG_TYPEDOBJECT_TOO_BIG, 0, JSEXN_ERR, "Type is too large to allocate")
// Typed array
MSG_DEF(JSMSG_BAD_INDEX, 0, JSEXN_RANGEERR, "invalid or out-of-range index")
-MSG_DEF(JSMSG_TYPED_ARRAY_BAD_ARGS, 0, JSEXN_ERR, "invalid arguments")
+MSG_DEF(JSMSG_TYPED_ARRAY_BAD_ARGS, 0, JSEXN_TYPEERR, "invalid arguments")
MSG_DEF(JSMSG_TYPED_ARRAY_BAD_OBJECT, 0, JSEXN_TYPEERR, "invalid object argument")
MSG_DEF(JSMSG_TYPED_ARRAY_BAD_INDEX, 0, JSEXN_ERR, "invalid or out-of-range index")
MSG_DEF(JSMSG_TYPED_ARRAY_NEGATIVE_ARG,1, JSEXN_ERR, "argument {0} must be >= 0")
MSG_DEF(JSMSG_TYPED_ARRAY_DETACHED, 0, JSEXN_TYPEERR, "attempting to access detached ArrayBuffer")
// Shared array buffer
MSG_DEF(JSMSG_SHARED_ARRAY_BAD_OBJECT, 0, JSEXN_TYPEERR, "invalid object argument")
MSG_DEF(JSMSG_SHARED_ARRAY_BAD_LENGTH, 0, JSEXN_RANGEERR, "length argument out of range")
deleted file mode 100644
--- a/js/src/tests/ecma_6/TypedObject/simd/float32x4shuffle.js
+++ /dev/null
@@ -1,53 +0,0 @@
-// |reftest| skip-if(!this.hasOwnProperty("SIMD"))
-var BUGNUMBER = 946042;
-var float32x4 = SIMD.float32x4;
-var int32x4 = SIMD.int32x4;
-
-var summary = 'float32x4 shuffle';
-
-function test() {
- print(BUGNUMBER + ": " + summary);
-
- // FIXME -- Bug 948379: Amend to check for correctness of border cases.
-
- var a = float32x4(1, 2, 3, 4);
- var c = SIMD.float32x4.shuffle(a, 0x1B);
- assertEq(c.x, 4);
- assertEq(c.y, 3);
- assertEq(c.z, 2);
- assertEq(c.w, 1);
-
- var d = SIMD.float32x4.shuffle(a, 0xFF);
- assertEq(d.x, 4);
- assertEq(d.y, 4);
- assertEq(d.z, 4);
- assertEq(d.w, 4);
-
- var d = SIMD.float32x4.shuffle(a, 0x0);
- assertEq(d.x, 1);
- assertEq(d.y, 1);
- assertEq(d.z, 1);
- assertEq(d.w, 1);
-
- var caught = false;
- try {
- var _ = SIMD.float32x4.shuffle(a, 0xFF + 1);
- } catch (e) {
- caught = true;
- }
- assertEq(caught, true, "Mask can't be more than 0xFF");
-
- var caught = false;
- try {
- var _ = SIMD.float32x4.shuffle(a, -1);
- } catch (e) {
- caught = true;
- }
- assertEq(caught, true, "Mask can't be less than 0");
-
- if (typeof reportCompare === "function")
- reportCompare(true, true);
-}
-
-test();
-
deleted file mode 100644
--- a/js/src/tests/ecma_6/TypedObject/simd/float32x4shufflemix.js
+++ /dev/null
@@ -1,54 +0,0 @@
-// |reftest| skip-if(!this.hasOwnProperty("SIMD"))
-var BUGNUMBER = 946042;
-var float32x4 = SIMD.float32x4;
-var int32x4 = SIMD.int32x4;
-
-var summary = 'float32x4 shuffleMix';
-
-function test() {
- print(BUGNUMBER + ": " + summary);
-
- // FIXME -- Bug 948379: Amend to check for correctness of border cases.
-
- var a = float32x4(1, 2, 3, 4);
- var b = float32x4(10, 20, 30, 40);
- var c = SIMD.float32x4.shuffleMix(a,b, 0x1B);
- assertEq(c.x, 4);
- assertEq(c.y, 3);
- assertEq(c.z, 20);
- assertEq(c.w, 10);
-
- var d = SIMD.float32x4.shuffleMix(a, b, 0xFF);
- assertEq(d.x, 4);
- assertEq(d.y, 4);
- assertEq(d.z, 40);
- assertEq(d.w, 40);
-
- var d = SIMD.float32x4.shuffleMix(a, b, 0x0);
- assertEq(d.x, 1);
- assertEq(d.y, 1);
- assertEq(d.z, 10);
- assertEq(d.w, 10);
-
- var caught = false;
- try {
- var _ = SIMD.float32x4.shuffleMix(a, b, 0xFF + 1);
- } catch (e) {
- caught = true;
- }
- assertEq(caught, true, "Mask can't be more than 0xFF");
-
- var caught = false;
- try {
- var _ = SIMD.float32x4.shuffleMix(a, b, -1);
- } catch (e) {
- caught = true;
- }
- assertEq(caught, true, "Mask can't be less than 0");
-
- if (typeof reportCompare === "function")
- reportCompare(true, true);
-}
-
-test();
-
deleted file mode 100644
--- a/js/src/tests/ecma_6/TypedObject/simd/int32x4shuffle.js
+++ /dev/null
@@ -1,51 +0,0 @@
-// |reftest| skip-if(!this.hasOwnProperty("SIMD"))
-var BUGNUMBER = 946042;
-var float32x4 = SIMD.float32x4;
-var int32x4 = SIMD.int32x4;
-
-var summary = 'int32x4 shuffle';
-
-function test() {
- print(BUGNUMBER + ": " + summary);
-
- var a = int32x4(1, 2, 3, 4);
- var c = SIMD.int32x4.shuffle(a, 0x1B);
- assertEq(c.x, 4);
- assertEq(c.y, 3);
- assertEq(c.z, 2);
- assertEq(c.w, 1);
-
- var d = SIMD.int32x4.shuffle(a, 0xFF);
- assertEq(d.x, 4);
- assertEq(d.y, 4);
- assertEq(d.z, 4);
- assertEq(d.w, 4);
-
- var d = SIMD.int32x4.shuffle(a, 0x0);
- assertEq(d.x, 1);
- assertEq(d.y, 1);
- assertEq(d.z, 1);
- assertEq(d.w, 1);
-
- var caught = false;
- try {
- var _ = SIMD.int32x4.shuffle(a, b, 0xFF + 1);
- } catch (e) {
- caught = true;
- }
- assertEq(caught, true, "Mask can't be more than 0xFF");
-
- var caught = false;
- try {
- var _ = SIMD.int32x4.shuffle(a, b, -1);
- } catch (e) {
- caught = true;
- }
- assertEq(caught, true, "Mask can't be less than 0");
-
- if (typeof reportCompare === "function")
- reportCompare(true, true);
-}
-
-test();
-
deleted file mode 100644
--- a/js/src/tests/ecma_6/TypedObject/simd/int32x4shufflemix.js
+++ /dev/null
@@ -1,53 +0,0 @@
-// |reftest| skip-if(!this.hasOwnProperty("SIMD"))
-var BUGNUMBER = 946042;
-var float32x4 = SIMD.float32x4;
-var int32x4 = SIMD.int32x4;
-
-var summary = 'int32x4 shuffleMix';
-
-function test() {
- print(BUGNUMBER + ": " + summary);
-
- var a = int32x4(1, 2, 3, 4);
- var b = int32x4(10, 20, 30, 40);
- var c = SIMD.int32x4.shuffleMix(a,b, 0x1B);
- assertEq(c.x, 4);
- assertEq(c.y, 3);
- assertEq(c.z, 20);
- assertEq(c.w, 10);
-
- var d = SIMD.int32x4.shuffleMix(a, b, 0xFF);
- assertEq(d.x, 4);
- assertEq(d.y, 4);
- assertEq(d.z, 40);
- assertEq(d.w, 40);
-
- var d = SIMD.int32x4.shuffleMix(a, b, 0x0);
- assertEq(d.x, 1);
- assertEq(d.y, 1);
- assertEq(d.z, 10);
- assertEq(d.w, 10);
-
- var caught = false;
- try {
- var _ = SIMD.int32x4.shuffleMix(a, b, 0xFF + 1);
- } catch (e) {
- caught = true;
- }
- assertEq(caught, true, "Mask can't be more than 0xFF");
-
- var caught = false;
- try {
- var _ = SIMD.int32x4.shuffleMix(a, b, -1);
- } catch (e) {
- caught = true;
- }
- assertEq(caught, true, "Mask can't be less than 0");
-
-
- if (typeof reportCompare === "function")
- reportCompare(true, true);
-}
-
-test();
-
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_6/TypedObject/simd/swizzle-shuffle.js
@@ -0,0 +1,149 @@
+// |reftest| skip-if(!this.hasOwnProperty("SIMD"))
+
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * https://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+var float32x4 = SIMD.float32x4;
+var int32x4 = SIMD.int32x4;
+
+function assertEq4(v, arr) {
+ assertEq(v.x, arr[0]);
+ assertEq(v.y, arr[1]);
+ assertEq(v.z, arr[2]);
+ assertEq(v.w, arr[3]);
+}
+
+function simdToArray(v) {
+ return [v.x, v.y, v.z, v.w];
+}
+
+function swizzle(arr, x, y, z, w) {
+ return [arr[x], arr[y], arr[z], arr[w]];
+}
+
+function testSwizzleForType(type) {
+ var v = type(1,2,3,4);
+
+ assertThrowsInstanceOf(() => type.swizzle() , TypeError);
+ assertThrowsInstanceOf(() => type.swizzle(v, 0) , TypeError);
+ assertThrowsInstanceOf(() => type.swizzle(v, 0, 1) , TypeError);
+ assertThrowsInstanceOf(() => type.swizzle(v, 0, 1, 2) , TypeError);
+ assertThrowsInstanceOf(() => type.swizzle(v, 0, 1, 2, 4) , TypeError);
+ assertThrowsInstanceOf(() => type.swizzle(v, 0, 1, 2, -1) , TypeError);
+ assertThrowsInstanceOf(() => type.swizzle(0, 1, 2, 3, v) , TypeError);
+
+ // Test all possible swizzles.
+ var x, y, z, w;
+ for (var i = 0; i < Math.pow(4, 4); i++) {
+ [x, y, z, w] = [i & 3, (i >> 2) & 3, (i >> 4) & 3, (i >> 6) & 3];
+ assertEq4(type.swizzle(v, x, y, z, w), swizzle(simdToArray(v), x, y, z, w));
+ }
+
+ // Test that the lane inputs are converted into an int32.
+ // n.b, order of evaluation of args is left-to-right.
+ var obj = {
+ x: 0,
+ valueOf: function() { return this.x++ }
+ };
+ assertEq4(type.swizzle(v, obj, obj, obj, obj), swizzle(simdToArray(v), 0, 1, 2, 3));
+
+ // Object for which ToInt32 will fail.
+ obj = {
+ valueOf: function() { throw new Error; }
+ };
+ assertThrowsInstanceOf(() => type.swizzle(v, 0, 1, 2, obj), Error);
+}
+
+function testSwizzleInt32x4() {
+ var v = int32x4(1, 2, 3, 4);
+
+ assertThrowsInstanceOf(function() {
+ float32x4.swizzle(v, 0, 0, 0, 0);
+ }, TypeError);
+
+ testSwizzleForType(int32x4);
+}
+
+function testSwizzleFloat32x4() {
+ var v = float32x4(1, 2, 3, 4);
+
+ assertThrowsInstanceOf(function() {
+ int32x4.swizzle(v, 0, 0, 0, 0);
+ }, TypeError);
+
+ testSwizzleForType(float32x4);
+}
+
+function shuffle(lhsa, rhsa, x, y, z, w) {
+ return [(x < 4 ? lhsa : rhsa)[x % 4],
+ (y < 4 ? lhsa : rhsa)[y % 4],
+ (z < 4 ? lhsa : rhsa)[z % 4],
+ (w < 4 ? lhsa : rhsa)[w % 4]];
+}
+
+function testShuffleForType(type) {
+ var lhs = type(1,2,3,4);
+ var rhs = type(5,6,7,8);
+
+ assertThrowsInstanceOf(() => type.shuffle(lhs) , TypeError);
+ assertThrowsInstanceOf(() => type.shuffle(lhs, rhs) , TypeError);
+ assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0) , TypeError);
+ assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, 1) , TypeError);
+ assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, 1, 2) , TypeError);
+ assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, 1, 2, -1) , TypeError);
+ assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, 1, 2, 8) , TypeError);
+ assertThrowsInstanceOf(() => type.shuffle(lhs, 0, 1, 2, 7, rhs) , TypeError);
+
+ // Test all possible shuffles.
+ var x, y, z, w;
+ for (var i = 0; i < Math.pow(8, 4); i++) {
+ [x, y, z, w] = [i & 7, (i >> 3) & 7, (i >> 6) & 7, (i >> 9) & 7];
+ assertEq4(type.shuffle(lhs, rhs, x, y, z, w),
+ shuffle(simdToArray(lhs), simdToArray(rhs), x, y, z, w));
+ }
+
+ // Test that the lane inputs are converted into an int32.
+ // n.b, order of evaluation of args is left-to-right.
+ var obj = {
+ x: 0,
+ valueOf: function() { return this.x++ }
+ };
+ assertEq4(type.shuffle(lhs, rhs, obj, obj, obj, obj),
+ shuffle(simdToArray(lhs),simdToArray(rhs), 0, 1, 2, 3));
+
+ // Object for which ToInt32 will fail.
+ obj = {
+ valueOf: function() { throw new Error; }
+ };
+ assertThrowsInstanceOf(() => type.shuffle(lhs, rhs, 0, 1, 2, obj), Error);
+}
+
+function testShuffleInt32x4() {
+ var v = int32x4(1, 2, 3, 4);
+
+ assertThrowsInstanceOf(function() {
+ float32x4.shuffle(v, v, 0, 0, 0, 0);
+ }, TypeError);
+
+ testShuffleForType(int32x4);
+}
+
+function testShuffleFloat32x4() {
+ var v = float32x4(1, 2, 3, 4);
+
+ assertThrowsInstanceOf(function() {
+ int32x4.shuffle(v, v, 0, 0, 0, 0);
+ }, TypeError);
+
+ testShuffleForType(float32x4);
+}
+
+testSwizzleInt32x4();
+testSwizzleFloat32x4();
+testShuffleInt32x4();
+testShuffleFloat32x4();
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);