From 20d37a6f2fa87887ca68540e83f1b017217caf8f Mon Sep 17 00:00:00 2001 From: dtig <dtig@users.noreply.github.com> Date: Mon, 18 Apr 2016 11:26:15 -0700 Subject: [PATCH] Add SIMD test suite and utility functions (#442) --- harness/simdUtilities.js | 426 +++++++++++++++++++++ test/built-ins/Simd/AUTHORS | 12 + test/built-ins/Simd/all_true.js | 29 ++ test/built-ins/Simd/any_true.js | 29 ++ test/built-ins/Simd/bit_conversion.js | 40 ++ test/built-ins/Simd/bit_preservation.js | 27 ++ test/built-ins/Simd/check.js | 35 ++ test/built-ins/Simd/constructor.js | 27 ++ test/built-ins/Simd/float_operators.js | 39 ++ test/built-ins/Simd/from.js | 34 ++ test/built-ins/Simd/from_bits.js | 31 ++ test/built-ins/Simd/loadn.js | 94 +++++ test/built-ins/Simd/logical_operators.js | 20 + test/built-ins/Simd/negate.js | 14 + test/built-ins/Simd/not.js | 20 + test/built-ins/Simd/numerical_operators.js | 40 ++ test/built-ins/Simd/operators.js | 58 +++ test/built-ins/Simd/replace_lane.js | 40 ++ test/built-ins/Simd/round_trip.js | 15 + test/built-ins/Simd/saturate.js | 26 ++ test/built-ins/Simd/select.js | 30 ++ test/built-ins/Simd/shift_operator.js | 55 +++ test/built-ins/Simd/shuffle.js | 59 +++ test/built-ins/Simd/storen.js | 86 +++++ test/built-ins/Simd/swizzle.js | 48 +++ 25 files changed, 1334 insertions(+) create mode 100644 harness/simdUtilities.js create mode 100644 test/built-ins/Simd/AUTHORS create mode 100644 test/built-ins/Simd/all_true.js create mode 100644 test/built-ins/Simd/any_true.js create mode 100644 test/built-ins/Simd/bit_conversion.js create mode 100644 test/built-ins/Simd/bit_preservation.js create mode 100644 test/built-ins/Simd/check.js create mode 100644 test/built-ins/Simd/constructor.js create mode 100644 test/built-ins/Simd/float_operators.js create mode 100644 test/built-ins/Simd/from.js create mode 100644 test/built-ins/Simd/from_bits.js create mode 100644 test/built-ins/Simd/loadn.js create mode 100644 test/built-ins/Simd/logical_operators.js create mode 100644 test/built-ins/Simd/negate.js create mode 100644 test/built-ins/Simd/not.js create mode 100644 test/built-ins/Simd/numerical_operators.js create mode 100644 test/built-ins/Simd/operators.js create mode 100644 test/built-ins/Simd/replace_lane.js create mode 100644 test/built-ins/Simd/round_trip.js create mode 100644 test/built-ins/Simd/saturate.js create mode 100644 test/built-ins/Simd/select.js create mode 100644 test/built-ins/Simd/shift_operator.js create mode 100644 test/built-ins/Simd/shuffle.js create mode 100644 test/built-ins/Simd/storen.js create mode 100644 test/built-ins/Simd/swizzle.js diff --git a/harness/simdUtilities.js b/harness/simdUtilities.js new file mode 100644 index 0000000000..efb4cd2d59 --- /dev/null +++ b/harness/simdUtilities.js @@ -0,0 +1,426 @@ +// Copyright (C) 2016 ecmascript_simd authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +function minNum(x, y) { + return x != x ? y : + y != y ? x : + Math.min(x, y); +} + +function maxNum(x, y) { + return x != x ? y : + y != y ? x : + Math.max(x, y); +} + +function sameValue(x, y) { + if (x == y) + return x != 0 || y != 0 || (1/x == 1/y); + + return x != x && y != y; +} + +function binaryMul(a, b) { return a * b; } +var binaryImul; +if (typeof Math.imul !== "undefined") { + binaryImul = Math.imul; +} else { + binaryImul = function(a, b) { + var ah = (a >>> 16) & 0xffff; + var al = a & 0xffff; + var bh = (b >>> 16) & 0xffff; + var bl = b & 0xffff; + // the shift by 0 fixes the sign on the high part + // the final |0 converts the unsigned value into a signed value + return ((al * bl) + (((ah * bl + al * bh) << 16) >>> 0)|0); + }; +} + +var _f32x4 = new Float32Array(4); +var _f64x2 = new Float64Array(_f32x4.buffer); +var _i32x4 = new Int32Array(_f32x4.buffer); +var _i16x8 = new Int16Array(_f32x4.buffer); +var _i8x16 = new Int8Array(_f32x4.buffer); +var _ui32x4 = new Uint32Array(_f32x4.buffer); +var _ui16x8 = new Uint16Array(_f32x4.buffer); +var _ui8x16 = new Uint8Array(_f32x4.buffer); + +var float32x4 = { + name: "Float32x4", + fn: SIMD.Float32x4, + floatLane: true, + signed: true, + numerical: true, + lanes: 4, + laneSize: 4, + interestingValues: [0, -0, 1, -1, 0.9, -0.9, 1.414, 0x7F, -0x80, -0x8000, + -0x80000000, 0x7FFF, 0x7FFFFFFF, Infinity, -Infinity, NaN], + view: Float32Array, + buffer: _f32x4, + mulFn: binaryMul, +} + +var int32x4 = { + name: "Int32x4", + fn: SIMD.Int32x4, + intLane: true, + signed: true, + numerical: true, + logical: true, + lanes: 4, + laneSize: 4, + minVal: -0x80000000, + maxVal: 0x7FFFFFFF, + interestingValues: [0, 1, -1, 0x40000000, 0x7FFFFFFF, -0x80000000], + view: Int32Array, + buffer: _i32x4, + mulFn: binaryImul, +} + +var int16x8 = { + name: "Int16x8", + fn: SIMD.Int16x8, + intLane: true, + signed: true, + numerical: true, + logical: true, + lanes: 8, + laneSize: 2, + laneMask: 0xFFFF, + minVal: -0x8000, + maxVal: 0x7FFF, + interestingValues: [0, 1, -1, 0x4000, 0x7FFF, -0x8000], + view: Int16Array, + buffer: _i16x8, + mulFn: binaryMul, +} + +var int8x16 = { + name: "Int8x16", + fn: SIMD.Int8x16, + intLane: true, + signed: true, + numerical: true, + logical: true, + lanes: 16, + laneSize: 1, + laneMask: 0xFF, + minVal: -0x80, + maxVal: 0x7F, + interestingValues: [0, 1, -1, 0x40, 0x7F, -0x80], + view: Int8Array, + buffer: _i8x16, + mulFn: binaryMul, +} + +var uint32x4 = { + name: "Uint32x4", + fn: SIMD.Uint32x4, + intLane: true, + unsigned: true, + numerical: true, + logical: true, + lanes: 4, + laneSize: 4, + minVal: 0, + maxVal: 0xFFFFFFFF, + interestingValues: [0, 1, 0x40000000, 0x7FFFFFFF, 0xFFFFFFFF], + view: Uint32Array, + buffer: _ui32x4, + mulFn: binaryImul, +} + +var uint16x8 = { + name: "Uint16x8", + fn: SIMD.Uint16x8, + intLane: true, + unsigned: true, + numerical: true, + logical: true, + lanes: 8, + laneSize: 2, + laneMask: 0xFFFF, + minVal: 0, + maxVal: 0xFFFF, + interestingValues: [0, 1, 0x4000, 0x7FFF, 0xFFFF], + view: Uint16Array, + buffer: _ui16x8, + mulFn: binaryMul, +} + +var uint8x16 = { + name: "Uint8x16", + fn: SIMD.Uint8x16, + intLane: true, + unsigned: true, + numerical: true, + logical: true, + lanes: 16, + laneSize: 1, + laneMask: 0xFF, + minVal: 0, + maxVal: 0xFF, + interestingValues: [0, 1, 0x40, 0x7F, 0xFF], + view: Int8Array, + buffer: _ui8x16, + mulFn: binaryMul, +} + +var bool32x4 = { + name: "Bool32x4", + fn: SIMD.Bool32x4, + boolLane: true, + logical: true, + lanes: 4, + laneSize: 4, + interestingValues: [true, false], +} + +var bool16x8 = { + name: "Bool16x8", + fn: SIMD.Bool16x8, + boolLane: true, + logical: true, + lanes: 8, + laneSize: 2, + interestingValues: [true, false], +} + +var bool8x16 = { + name: "Bool8x16", + fn: SIMD.Bool8x16, + boolLane: true, + logical: true, + lanes: 16, + laneSize: 1, + interestingValues: [true, false], +} + +// Filter functions. +function isFloatType(type) { return type.floatLane; } +function isIntType(type) { return type.intLane; } +function isBoolType(type) { return type.boolLane; } +function isNumerical(type) { return type.numerical; } +function isLogical(type) { return type.logical; } +function isSigned(type) { return type.signed; } +function isSignedIntType(type) { return type.intLane && type.signed; } +function isUnsignedIntType(type) { return type.intLane && type.unsigned; } +function isSmallIntType(type) { return type.intLane && type.lanes >= 8; } +function isSmallUnsignedIntType(type) { + return type.intLane && type.unsigned && type.lanes >= 8; +} +function hasLoadStore123(type) { return !type.boolLane && type.lanes == 4; } + +// Each SIMD type has a corresponding Boolean SIMD type, which is returned by +// relational ops. +float32x4.boolType = int32x4.boolType = uint32x4.boolType = bool32x4; +int16x8.boolType = uint16x8.boolType = bool16x8; +int8x16.boolType = uint8x16.boolType = bool8x16; + +// SIMD fromTIMD types. +float32x4.from = [int32x4, uint32x4]; +int32x4.from = [float32x4]; +int16x8.from = []; +int8x16.from = []; +uint32x4.from = [float32x4]; +uint16x8.from = [int16x8]; +uint8x16.from = [int8x16]; + +// SIMD fromBits types. +float32x4.fromBits = [int32x4, int16x8, int8x16, uint32x4, uint16x8, uint8x16]; +int32x4.fromBits = [float32x4, int16x8, int8x16, uint32x4, uint16x8, uint8x16]; +int16x8.fromBits = [float32x4, int32x4, int8x16, uint32x4, uint16x8, uint8x16]; +int8x16.fromBits = [float32x4, int32x4, int16x8, uint32x4, uint16x8, uint8x16]; +uint32x4.fromBits = [float32x4, int32x4, int16x8, int8x16, uint16x8, uint8x16]; +uint16x8.fromBits = [float32x4, int32x4, int16x8, int8x16, uint32x4, uint8x16]; +uint8x16.fromBits = [float32x4, int32x4, int16x8, int8x16, uint32x4, uint16x8]; + +var simdTypes = [float32x4, + int32x4, int16x8, int8x16, + uint32x4, uint16x8, uint8x16, + bool32x4, bool16x8, bool8x16]; + +if (typeof simdPhase2 !== "undefined") { + var float64x2 = { + name: "Float64x2", + fn: SIMD.Float64x2, + floatLane: true, + signed: true, + numerical: true, + lanes: 2, + laneSize: 8, + interestingValues: [0, -0, 1, -1, 1.414, 0x7F, -0x80, -0x8000, -0x80000000, + 0x7FFF, 0x7FFFFFFF, Infinity, -Infinity, NaN], + view: Float64Array, + buffer: _f64x2, + mulFn: binaryMul, + } + + var bool64x2 = { + name: "Bool64x2", + fn: SIMD.Bool64x2, + boolLane: true, + lanes: 2, + laneSize: 8, + interestingValues: [true, false], + } + + float64x2.boolType = bool64x2; + + float32x4.fromBits.push(float64x2); + int32x4.fromBits.push(float64x2); + int16x8.fromBits.push(float64x2); + int8x16.fromBits.push(float64x2); + uint32x4.fromBits.push(float64x2); + uint16x8.fromBits.push(float64x2); + uint8x16.fromBits.push(float64x2); + + float64x2.fromBits = [float32x4, int32x4, int16x8, int8x16, + uint32x4, uint16x8, uint8x16]; + + int32x4.fromBits = [float32x4, int16x8, int8x16, uint32x4, + uint16x8, uint8x16]; + int16x8.fromBits = [float32x4, int32x4, int8x16, uint32x4, + uint16x8, uint8x16]; + int8x16.fromBits = [float32x4, int32x4, int16x8, uint32x4, + uint16x8, uint8x16]; + uint32x4.fromBits = [float32x4, int32x4, int16x8, int8x16, + uint16x8, uint8x16]; + uint16x8.fromBits = [float32x4, int32x4, int16x8, int8x16, + uint32x4, uint8x16]; + uint8x16.fromBits = [float32x4, int32x4, int16x8, int8x16, + uint32x4, uint16x8]; + + simdTypes.push(float64x2); + simdTypes.push(bool64x2); +} + +// SIMD utility functions. + +// Create a value for testing, with vanilla lane values, i.e. [0, 1, 2, ..] +// for numeric types, [false, true, true, ..] for boolean types. These test +// values shouldn't contain NaNs or other "interesting" values. +function createTestValue(type) { + var lanes = []; + for (var i = 0; i < type.lanes; i++) + lanes.push(i); + return type.fn.apply(type.fn, lanes); +} + +function createSplatValue(type, v) { + var lanes = []; + for (var i = 0; i < type.lanes; i++) + lanes.push(v); + return type.fn.apply(type.fn, lanes); +} + +// SIMD reference functions. + +// Returns converted array buffer value of specified type. +function simdConvert(type, value) { + if (type.buffer === undefined) return !!value; // bool types + type.buffer[0] = value; + return type.buffer[0]; +} + +function checkValue(type, a, expect) { + var fail = false; + for (var i = 0; i < type.lanes; i++) { + var v = type.fn.extractLane(a, i); + var ev = simdConvert(type, expect(i)); + if (!sameValue(ev, v) && Math.abs(ev - v) >= 0.00001) + fail = true; + } + if (fail) { + var lanes = []; + for (var i = 0; i < type.lanes; i++){ + lanes.push(simdConvert(type, expect(i))); + } + $ERROR("expected SIMD." + type.name + "(" + lanes + + ") but found " + a.toString()); + } +} + +// SIMD reference functions. + +// Reference implementation of toLocaleString. +function simdToLocaleString(type, value) { + value = type.fn.check(value); + var str = "SIMD." + type.name + "("; + str += type.fn.extractLane(value, 0).toLocaleString(); + for (var i = 1; i < type.lanes; i++) { + str += "," + type.fn.extractLane(value, i).toLocaleString(); + } + return str + ")"; +} + +function equalInt32x4(a, b) { + assert.sameValue(SIMD.Int32x4.extractLane(a, 0), + SIMD.Int32x4.extractLane(b, 0)); + assert.sameValue(SIMD.Int32x4.extractLane(a, 1), + SIMD.Int32x4.extractLane(b, 1)); + assert.sameValue(SIMD.Int32x4.extractLane(a, 2), + SIMD.Int32x4.extractLane(b, 2)); + assert.sameValue(SIMD.Int32x4.extractLane(a, 3), + SIMD.Int32x4.extractLane(b, 3)); +} + +// Compare unary op's behavior to ref op at each lane. +function testUnaryOp(type, op, refOp) { + assert.sameValue("function", typeof type.fn[op]); + for (var v of type.interestingValues) { + var expected = simdConvert(type, refOp(v)); + var a = type.fn.splat(v); + var result = type.fn[op](a); + checkValue(type, result, function(index) { return expected; }); + } +} + +// Compare binary op's behavior to ref op at each lane with the Cartesian +// product of the given values. +function testBinaryOp(type, op, refOp) { + assert.sameValue("function", typeof type.fn[op]); + var zero = type.fn(); + for (var av of type.interestingValues) { + for (var bv of type.interestingValues) { + var expected = simdConvert(type, refOp(simdConvert(type, av), + simdConvert(type, bv))); + var a = type.fn.splat(av); + var b = type.fn.splat(bv); + var result = type.fn[op](a, b); + checkValue(type, result, function(index) { return expected; }); + } + } +} + +// Compare relational op's behavior to ref op at each lane with the Cartesian +// product of the given values. +function testRelationalOp(type, op, refOp) { + assert.sameValue("function", typeof type.fn[op]); + var zero = type.fn(); + for (var av of type.interestingValues) { + for (var bv of type.interestingValues) { + var expected = refOp(simdConvert(type, av), simdConvert(type, bv)); + var a = type.fn.splat(av); + var b = type.fn.splat(bv); + var result = type.fn[op](a, b); + checkValue(type.boolType, result, function(index) { return expected; }); + } + } +} + +// Test utilities. +var currentName = "<global>"; +var skipValueTests = false; + +function testSimdFunction(name, func) { + currentName = name; + if (typeof skipValueTests !== "undefined" && skipValueTests && + name.indexOf("value semantics") != -1) return; + try { + func(); + } catch (e) { + e.message += " (Testing with " + name + ".)"; + throw e; + } +} diff --git a/test/built-ins/Simd/AUTHORS b/test/built-ins/Simd/AUTHORS new file mode 100644 index 0000000000..f566d7e48b --- /dev/null +++ b/test/built-ins/Simd/AUTHORS @@ -0,0 +1,12 @@ +Arun Purushan <arun.etm@gmail.com> +Benjamin Bouvier <public@benj.me> +Bill Budge <bbudge@chromium.org> +Dan Ehrenberg <littledan@chromium.org> +Dan Gohman <sunfish@mozilla.com> +Deepti Gandluri <gdeepti@google.com> +Florian Scholz <elchi3@elchi3.de> +Heidi Pan <heidi.pan@intel.com> +Jakob Stoklund Olesen <jolesen@mozilla.com> +John McCutchan <john@johnmccutchan.com> +Ningxin Hu <ningxin.hu@intel.com> +Peter Jensen <peter.jensen@intel.com> diff --git a/test/built-ins/Simd/all_true.js b/test/built-ins/Simd/all_true.js new file mode 100644 index 0000000000..698c64d6e5 --- /dev/null +++ b/test/built-ins/Simd/all_true.js @@ -0,0 +1,29 @@ +// Copyright (C) 2016 ecmascript_simd authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: simd-all-true +description: AllTrue returns true if all the SIMDElements are true. +includes: [simdUtilities.js] +---*/ + +function testAllTrue(type) { + assert.sameValue('function', typeof type.fn.allTrue); + // All lanes 'true'. + var a = type.fn.splat(true); + assert(type.fn.allTrue(a)); + // One lane 'false'. + for (var i = 0; i < type.lanes; i++) { + a = type.fn.replaceLane(a, i, false); + assert(!type.fn.allTrue(a)); + } + // All lanes 'false'. + a = type.fn.splat(false); + assert(!type.fn.allTrue(a)); +} + +simdTypes.filter(isBoolType).forEach(function(type) { + testSimdFunction(type.name + ' allTrue', function() { + testAllTrue(type, 'allTrue'); + }); +}); diff --git a/test/built-ins/Simd/any_true.js b/test/built-ins/Simd/any_true.js new file mode 100644 index 0000000000..0412c800c3 --- /dev/null +++ b/test/built-ins/Simd/any_true.js @@ -0,0 +1,29 @@ +// Copyright (C) 2016 ecmascript_simd authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: simd-any-true +description: AllTrue returns true if all the SIMDElements are true. +includes: [simdUtilities.js] +---*/ + +function testAnyTrue(type) { + assert.sameValue('function', typeof type.fn.anyTrue); + // All lanes 'false'. + var a = type.fn.splat(false); + assert(!type.fn.anyTrue(a)); + // One lane 'true'. + for (var i = 0; i < type.lanes; i++) { + a = type.fn.replaceLane(a, i, true); + assert(type.fn.anyTrue(a)); + } + // All lanes 'true'. + a = type.fn.splat(true); + assert(type.fn.anyTrue(a)); +} + +simdTypes.filter(isBoolType).forEach(function(type) { + testSimdFunction(type.name + ' anyTrue', function() { + testAnyTrue(type, 'anyTrue'); + }); +}); diff --git a/test/built-ins/Simd/bit_conversion.js b/test/built-ins/Simd/bit_conversion.js new file mode 100644 index 0000000000..e5fceb73d1 --- /dev/null +++ b/test/built-ins/Simd/bit_conversion.js @@ -0,0 +1,40 @@ +// Copyright (C) 2016 ecmascript_simd authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: pending +description: Tests Float32x4 Int32x4 bit conversion. +includes: [simdUtilities.js] +---*/ + +testSimdFunction('Float32x4 Int32x4 bit conversion', function() { + var m = SIMD.Int32x4(0x3F800000, 0x40000000, 0x40400000, 0x40800000); + var n = SIMD.Float32x4.fromInt32x4Bits(m); + assert.sameValue(1.0, SIMD.Float32x4.extractLane(n, 0)); + assert.sameValue(2.0, SIMD.Float32x4.extractLane(n, 1)); + assert.sameValue(3.0, SIMD.Float32x4.extractLane(n, 2)); + assert.sameValue(4.0, SIMD.Float32x4.extractLane(n, 3)); + n = SIMD.Float32x4(5.0, 6.0, 7.0, 8.0); + m = SIMD.Int32x4.fromFloat32x4Bits(n); + assert.sameValue(0x40A00000, SIMD.Int32x4.extractLane(m, 0)); + assert.sameValue(0x40C00000, SIMD.Int32x4.extractLane(m, 1)); + assert.sameValue(0x40E00000, SIMD.Int32x4.extractLane(m, 2)); + assert.sameValue(0x41000000, SIMD.Int32x4.extractLane(m, 3)); + // Flip sign using bit-wise operators. + n = SIMD.Float32x4(9.0, 10.0, 11.0, 12.0); + m = SIMD.Int32x4(0x80000000, 0x80000000, 0x80000000, 0x80000000); + var nMask = SIMD.Int32x4.fromFloat32x4Bits(n); + nMask = SIMD.Int32x4.xor(nMask, m); // flip sign. + n = SIMD.Float32x4.fromInt32x4Bits(nMask); + assert.sameValue(-9.0, SIMD.Float32x4.extractLane(n, 0)); + assert.sameValue(-10.0, SIMD.Float32x4.extractLane(n, 1)); + assert.sameValue(-11.0, SIMD.Float32x4.extractLane(n, 2)); + assert.sameValue(-12.0, SIMD.Float32x4.extractLane(n, 3)); + nMask = SIMD.Int32x4.fromFloat32x4Bits(n); + nMask = SIMD.Int32x4.xor(nMask, m); // flip sign. + n = SIMD.Float32x4.fromInt32x4Bits(nMask); + assert.sameValue(9.0, SIMD.Float32x4.extractLane(n, 0)); + assert.sameValue(10.0, SIMD.Float32x4.extractLane(n, 1)); + assert.sameValue(11.0, SIMD.Float32x4.extractLane(n, 2)); + assert.sameValue(12.0, SIMD.Float32x4.extractLane(n, 3)); +}); diff --git a/test/built-ins/Simd/bit_preservation.js b/test/built-ins/Simd/bit_preservation.js new file mode 100644 index 0000000000..fb345d6385 --- /dev/null +++ b/test/built-ins/Simd/bit_preservation.js @@ -0,0 +1,27 @@ +// Copyright (C) 2016 ecmascript_simd authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: pending +description: Tests SIMD load and store bit preservation. +includes: [simdUtilities.js] +---*/ + +testSimdFunction('Float32x4 Int32x4 load/store bit preservation', function() { + // NaNs should stay unmodified when storing and loading to Float32Array + var taf32 = new Float32Array(4); + var tai32 = new Int32Array(4); + var i4a, i4b; + i4a = SIMD.Int32x4(0x7fc00000,0x7fe00000,0x7ff00000,0x7ff80000); + SIMD.Int32x4.store(taf32, 0, i4a); + i4b = SIMD.Int32x4.load(taf32, 0); + equalInt32x4(i4a, i4b); + + // NaNs should stay unmodified when loading as Float32x4 and + // storing as Int32x4 + SIMD.Int32x4.store(taf32, 0, i4a); + var f4 = SIMD.Float32x4.load(taf32, 0); + SIMD.Float32x4.store(tai32, 0, f4); + i4b = SIMD.Int32x4.load(tai32, 0); + equalInt32x4(i4a, i4b); +}); diff --git a/test/built-ins/Simd/check.js b/test/built-ins/Simd/check.js new file mode 100644 index 0000000000..c73ca4d4eb --- /dev/null +++ b/test/built-ins/Simd/check.js @@ -0,0 +1,35 @@ +// Copyright (C) 2016 ecmascript_simd authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: simd-check +description: Checks if a SIMDTypeDescriptor is not a SIMDDescriptor. +includes: [simdUtilities.js] +---*/ + +function testCheck(type) { + assert.sameValue('function', typeof type.fn.check); + // Other SIMD types shouldn't check for this type. + var a = type.fn(); + for (var otherType of simdTypes) { + if (otherType === type) { + var result = type.fn.check(a); + checkValue(type, result, function(index) { + return type.fn.extractLane(a, index); + }); + assert.sameValue(a, type.fn.check(a)); + } else { + assert.throws(TypeError, function() { otherType.check(a); }); + } + } + // Neither should other types. + for (var x of [ {}, "", 0, 1, true, false, undefined, null, NaN, Infinity]) { + assert.throws(TypeError, function() { type.fn.check(x); }); + } +} + +simdTypes.forEach(function(type) { + testSimdFunction(type.name + ' check', function() { + testCheck(type); + }); +}); diff --git a/test/built-ins/Simd/constructor.js b/test/built-ins/Simd/constructor.js new file mode 100644 index 0000000000..d71d0a5efe --- /dev/null +++ b/test/built-ins/Simd/constructor.js @@ -0,0 +1,27 @@ +// Copyright (C) 2016 ecmascript_simd authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: simd-wrapper +description: Test the constructor and splat with the given lane values. +includes: [simdUtilities.js] +---*/ + +function testConstructor(type) { + assert.sameValue('function', typeof type.fn); + assert.sameValue('function', typeof type.fn.splat); + for (var v of type.interestingValues) { + var expected = simdConvert(type, v); + var result = createSplatValue(type, v); + checkValue(type, result, function(index) { return expected; }); + // splat. + result = type.fn.splat(v); + checkValue(type, result, function(index) { return expected; }); + } +} + +simdTypes.forEach(function(type) { + testSimdFunction(type.name + ' constructor', function() { + testConstructor(type); + }); +}); diff --git a/test/built-ins/Simd/float_operators.js b/test/built-ins/Simd/float_operators.js new file mode 100644 index 0000000000..37a55c8e5b --- /dev/null +++ b/test/built-ins/Simd/float_operators.js @@ -0,0 +1,39 @@ +// Copyright (C) 2016 ecmascript_simd authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: constructor-properties +description: Test floating point SIMD operations. +includes: [simdUtilities.js] +---*/ + +simdTypes.filter(isFloatType).forEach(function(type) { + testSimdFunction(type.name + ' div', function() { + testBinaryOp(type, 'div', function(a, b) { return a / b; }); + }); + testSimdFunction(type.name + ' abs', function() { + testUnaryOp(type, 'abs', Math.abs); + }); + testSimdFunction(type.name + ' min', function() { + testBinaryOp(type, 'min', Math.min); + }); + testSimdFunction(type.name + ' max', function() { + testBinaryOp(type, 'max', Math.max); + }); + testSimdFunction(type.name + ' minNum', function() { + testBinaryOp(type, 'minNum', minNum); + }); + testSimdFunction(type.name + ' maxNum', function() { + testBinaryOp(type, 'maxNum', maxNum); + }); + testSimdFunction(type.name + ' sqrt', function() { + testUnaryOp(type, 'sqrt', function(a) { return Math.sqrt(a); }); + }); + testSimdFunction(type.name + ' reciprocalApproximation', function() { + testUnaryOp(type, 'reciprocalApproximation', function(a) { return 1 / a; }); + }); + testSimdFunction(type.name + ' reciprocalSqrtApproximation', function() { + testUnaryOp(type, 'reciprocalSqrtApproximation', function(a) { + return 1 / Math.sqrt(a); }); + }); +}) diff --git a/test/built-ins/Simd/from.js b/test/built-ins/Simd/from.js new file mode 100644 index 0000000000..ad67c6854b --- /dev/null +++ b/test/built-ins/Simd/from.js @@ -0,0 +1,34 @@ +// Copyright (C) 2016 ecmascript_simd authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: simd-to-timd-logical +description: Tests From<type> functions. +includes: [simdUtilities.js] +---*/ + +function testFrom(toType, fromType, name) { + assert.sameValue('function', typeof toType.fn[name]); + for (var v of fromType.interestingValues) { + var fromValue = createSplatValue(fromType, v); + v = Math.trunc(simdConvert(fromType, v)); + if (toType.minVal !== undefined && + !(toType.minVal <= v && v <= toType.maxVal)) { + assert.throws(RangeError, function() { toType.fn[name](fromValue) }); + } else { + v = simdConvert(toType, v); + var result = toType.fn[name](fromValue); + checkValue(toType, result, function(index) { return v; }); + } + } +} + +simdTypes.forEach(function(toType) { + if (!toType.from) return; + for (var fromType of toType.from) { + var fn = 'from' + fromType.name; + testSimdFunction(toType.name + ' ' + fn, function() { + testFrom(toType, fromType, fn); + }); + } +}); diff --git a/test/built-ins/Simd/from_bits.js b/test/built-ins/Simd/from_bits.js new file mode 100644 index 0000000000..5a6f130b41 --- /dev/null +++ b/test/built-ins/Simd/from_bits.js @@ -0,0 +1,31 @@ +// Copyright (C) 2016 ecmascript_simd authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: simd-to-timd +description: From<type>Bits functions. +includes: [simdUtilities.js] +---*/ + +function testFromBits(toType, fromType, name) { + assert.sameValue('function', typeof toType.fn[name]); + for (var v of fromType.interestingValues) { + var fromValue = createSplatValue(fromType, v); + var result = toType.fn[name](fromValue); + for (var i = 0; i < fromType.lanes; i++) + fromType.buffer[i] = fromType.fn.extractLane(fromValue, i); + checkValue(toType, result, function(index) { + return toType.buffer[index]; + }); + } +} + +simdTypes.forEach(function(toType) { + if (!toType.fromBits) return; + for (var fromType of toType.fromBits) { + var fn = 'from' + fromType.name + 'Bits'; + testSimdFunction(toType.name + ' ' + fn, function() { + testFromBits(toType, fromType, fn); + }); + } +}); diff --git a/test/built-ins/Simd/loadn.js b/test/built-ins/Simd/loadn.js new file mode 100644 index 0000000000..616a959bf9 --- /dev/null +++ b/test/built-ins/Simd/loadn.js @@ -0,0 +1,94 @@ +// Copyright (C) 2016 ecmascript_simd authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: simd-load-from-tarray +description: Tests SIMD load functions. +includes: [simdUtilities.js] +---*/ + +function testLoad(type, name, count) { + var loadFn = type.fn[name]; + assert.sameValue('function', typeof loadFn); + var bufLanes = 2 * type.lanes; // Test all alignments. + var bufSize = bufLanes * type.laneSize + 8; // Extra for over-alignment test. + var ab = new ArrayBuffer(bufSize); + var buf = new type.view(ab); + for (var i = 0; i < bufLanes; i++) buf[i] = i; // Number buffer sequentially. + // Test aligned loads. + for (var i = 0; i < type.lanes; i++) { + var a = loadFn(buf, i); + checkValue(type, a, function(index) { + return index < count ? i + index : 0; + }); + } + + // Test index coercions + // Unlike typedArray[index], non-canonical strings are allowed here. + checkValue(type, loadFn(buf, "0"), + function(index) { return index < count ? index : 0; }); + checkValue(type, loadFn(buf, " -0.0 "), + function(index) { return index < count ? index : 0; }); + checkValue(type, loadFn(buf, "00"), + function(index) { return index < count ? index : 0; }); + checkValue(type, loadFn(buf, false), + function(index) { return index < count ? index : 0; }); + checkValue(type, loadFn(buf, null), + function(index) { return index < count ? index : 0; }); + checkValue(type, loadFn(buf, "01"), + function(index) { return index < count ? 1 + index : 0; }); + checkValue(type, loadFn(buf, " +1e0"), + function(index) { return index < count ? 1 + index : 0; }); + checkValue(type, loadFn(buf, true), + function(index) { return index < count ? 1 + index : 0; }); + + // Test the 2 possible over-alignments. + var f64 = new Float64Array(ab); + var stride = 8 / type.laneSize; + for (var i = 0; i < 1; i++) { + var a = loadFn(f64, i); + checkValue(type, a, function(index) { + return index < count ? stride * i + index : 0; + }); + } + // Test the 7 possible mis-alignments. + var i8 = new Int8Array(ab); + for (var misalignment = 1; misalignment < 8; misalignment++) { + // Shift the buffer up by 1 byte. + for (var i = i8.length - 1; i > 0; i--) + i8[i] = i8[i - 1]; + var a = loadFn(i8, misalignment); + checkValue(type, a, function(index) { + return index < count ? i + index : 0; + }); + } + + function testIndexCheck(buf, index, err) { + assert.throws(err, function () { loadFn(buf, index); }); + } + testIndexCheck(buf, -1, RangeError); + testIndexCheck(buf, 0.7, RangeError); + testIndexCheck(buf, -0.1, RangeError); + testIndexCheck(buf, NaN, RangeError); + testIndexCheck(buf, bufSize / type.laneSize - count + 1, RangeError); + testIndexCheck(buf.buffer, 1, TypeError); + testIndexCheck(buf, "a", RangeError); +} + +simdTypes.filter(isNumerical).forEach(function(type) { + testSimdFunction(type.name + ' load', function() { + testLoad(type, 'load', type.lanes); + }); +}); + +simdTypes.filter(hasLoadStore123).forEach(function(type) { + testSimdFunction(type.name + ' load1', function() { + testLoad(type, 'load1', 1); + }); + testSimdFunction(type.name + ' load2', function() { + testLoad(type, 'load2', 2); + }); + testSimdFunction(type.name + ' load3', function() { + testLoad(type, 'load3', 3); + }); +}); diff --git a/test/built-ins/Simd/logical_operators.js b/test/built-ins/Simd/logical_operators.js new file mode 100644 index 0000000000..4bc892f725 --- /dev/null +++ b/test/built-ins/Simd/logical_operators.js @@ -0,0 +1,20 @@ +// Copyright (C) 2016 ecmascript_simd authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: constructor-properties +description: Test SIMD Logical operations. +includes: [simdUtilities.js] +---*/ + +simdTypes.filter(isLogical).forEach(function(type) { + testSimdFunction(type.name + ' and', function() { + testBinaryOp(type, 'and', function(a, b) { return a & b; }); + }); + testSimdFunction(type.name + ' or', function() { + testBinaryOp(type, 'or', function(a, b) { return a | b; }); + }); + testSimdFunction(type.name + ' xor', function() { + testBinaryOp(type, 'xor', function(a, b) { return a ^ b; }); + }); +}); diff --git a/test/built-ins/Simd/negate.js b/test/built-ins/Simd/negate.js new file mode 100644 index 0000000000..7ee9f24d16 --- /dev/null +++ b/test/built-ins/Simd/negate.js @@ -0,0 +1,14 @@ +// Copyright (C) 2016 ecmascript_simd authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: simd-neg +description: Tests the unary '-' operation. +includes: [simdUtilities.js] +---*/ + +simdTypes.filter(isNumerical).forEach(function(type) { + testSimdFunction(type.name + ' neg', function() { + testUnaryOp(type, 'neg', function(a) { return -a; }); + }); +}); diff --git a/test/built-ins/Simd/not.js b/test/built-ins/Simd/not.js new file mode 100644 index 0000000000..08f645ec1e --- /dev/null +++ b/test/built-ins/Simd/not.js @@ -0,0 +1,20 @@ +// Copyright (C) 2016 ecmascript_simd authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: simd-not +description: Tests the unary not operation. +includes: [simdUtilities.js] +---*/ + +simdTypes.filter(isIntType).forEach(function(type) { + testSimdFunction(type.name + ' not', function() { + testUnaryOp(type, 'not', function(a) { return ~a; }); + }); +}); + +simdTypes.filter(isBoolType).forEach(function(type) { + testSimdFunction(type.name + ' not', function() { + testUnaryOp(type, 'not', function(a) { return !a; }); + }); +}); diff --git a/test/built-ins/Simd/numerical_operators.js b/test/built-ins/Simd/numerical_operators.js new file mode 100644 index 0000000000..ea032661e6 --- /dev/null +++ b/test/built-ins/Simd/numerical_operators.js @@ -0,0 +1,40 @@ +// Copyright (C) 2016 ecmascript_simd authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: constructor-properties +description: Tests the SIMD numerical operations. +includes: [simdUtilities.js] +---*/ + +simdTypes.filter(isNumerical).forEach(function(type) { + testSimdFunction(type.name + ' equal', function() { + testRelationalOp(type, 'equal', function(a, b) { return a == b; }); + }); + testSimdFunction(type.name + ' notEqual', function() { + testRelationalOp(type, 'notEqual', function(a, b) { return a != b; }); + }); + testSimdFunction(type.name + ' lessThan', function() { + testRelationalOp(type, 'lessThan', function(a, b) { return a < b; }); + }); + testSimdFunction(type.name + ' lessThanOrEqual', function() { + testRelationalOp(type, 'lessThanOrEqual', function(a, b) { + return a <= b; + }); + }); + testSimdFunction(type.name + ' greaterThan', function() { + testRelationalOp(type, 'greaterThan', function(a, b) { return a > b; }); + }); + testSimdFunction(type.name + ' greaterThanOrEqual', function() { + testRelationalOp(type, 'greaterThanOrEqual', function(a, b) { return a >= b; }); + }); + testSimdFunction(type.name + ' add', function() { + testBinaryOp(type, 'add', function(a, b) { return a + b; }); + }); + testSimdFunction(type.name + ' sub', function() { + testBinaryOp(type, 'sub', function(a, b) { return a - b; }); + }); + testSimdFunction(type.name + ' mul', function() { + testBinaryOp(type, 'mul', type.mulFn); + }); +}); diff --git a/test/built-ins/Simd/operators.js b/test/built-ins/Simd/operators.js new file mode 100644 index 0000000000..f638a5ff9c --- /dev/null +++ b/test/built-ins/Simd/operators.js @@ -0,0 +1,58 @@ +// Copyright (C) 2016 ecmascript_simd authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: pending +description: Test SIMD operators. +includes: [simdUtilities.js] +---*/ + +function testOperators(type) { + var inst = createTestValue(type); + assert.throws(TypeError, function() { Number(inst) }); + assert.throws(TypeError, function() { +inst }); + assert.throws(TypeError, function() { -inst }); + assert.throws(TypeError, function() { ~inst }); + assert.throws(TypeError, function() { Math.fround(inst) }); + assert.throws(TypeError, function() { inst|0} ); + assert.throws(TypeError, function() { inst&0 }); + assert.throws(TypeError, function() { inst^0 }); + assert.throws(TypeError, function() { inst>>>0 }); + assert.throws(TypeError, function() { inst>>0 }); + assert.throws(TypeError, function() { inst<<0 }); + assert.throws(TypeError, function() { (inst + inst) }); + assert.throws(TypeError, function() { inst - inst }); + assert.throws(TypeError, function() { inst * inst }); + assert.throws(TypeError, function() { inst / inst }); + assert.throws(TypeError, function() { inst % inst }); + assert.throws(TypeError, function() { inst < inst }); + assert.throws(TypeError, function() { inst > inst }); + assert.throws(TypeError, function() { inst <= inst }); + assert.throws(TypeError, function() { inst >= inst }); + assert.throws(TypeError, function() { inst(); }); + + assert.sameValue(inst[0], undefined); + assert.sameValue(inst.a, undefined); + assert.sameValue(!inst, false); + assert.sameValue(!inst, false); + assert.sameValue(inst ? 1 : 2, 1); + assert.sameValue(inst ? 1 : 2, 1); + + assert.sameValue('function', typeof inst.toString); + assert.sameValue('function', typeof inst.toLocaleString); + assert.sameValue(inst.toLocaleString(), simdToLocaleString(type, inst)); + + var eval_value = eval(inst.toString()); + var value = type.fn.check(inst); + for(var i = 0; i < type.lanes; i++) { + assert.sameValue(type.fn.extractLane(eval_value, i), + type.fn.extractLane(value, i)); + } + // TODO: test valueOf? +} + +simdTypes.forEach(function(type) { + testSimdFunction(type.name + ' operators', function() { + testOperators(type); + }); +}); diff --git a/test/built-ins/Simd/replace_lane.js b/test/built-ins/Simd/replace_lane.js new file mode 100644 index 0000000000..42b72d619d --- /dev/null +++ b/test/built-ins/Simd/replace_lane.js @@ -0,0 +1,40 @@ +// Copyright (C) 2016 ecmascript_simd authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: simd-abstract-replace-lane +description: Tests SIMD ReplaceLane. +includes: [simdUtilities.js] +---*/ + +function testReplaceLane(type) { + assert.sameValue('function', typeof type.fn.replaceLane); + var a = createTestValue(type); + for (var v of type.interestingValues) { + var expected = simdConvert(type, v); + for (var i = 0; i < type.lanes; i++) { + var result = type.fn.replaceLane(a, i, v); + checkValue(type, result, + function(index) { + return index == i ? expected : type.fn.extractLane(a, index); + }); + } + } + + function testIndexCheck(index, err) { + assert.throws(err, function() { type.fn.replaceLane(a, index, 0); }); + } + testIndexCheck(type.lanes, RangeError); + testIndexCheck(13.37, TypeError); + testIndexCheck(undefined, TypeError); + testIndexCheck({}, TypeError); + testIndexCheck('yo', TypeError); + testIndexCheck(-1, RangeError); + testIndexCheck(128, RangeError); +} + +simdTypes.forEach(function(type) { + testSimdFunction(type.name + ' replaceLane', function() { + testReplaceLane(type); + }); +}); diff --git a/test/built-ins/Simd/round_trip.js b/test/built-ins/Simd/round_trip.js new file mode 100644 index 0000000000..6c9d56399d --- /dev/null +++ b/test/built-ins/Simd/round_trip.js @@ -0,0 +1,15 @@ +// Copyright (C) 2016 ecmascript_simd authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: pending +description: Test round trip. +includes: [simdUtilities.js] +---*/ + +testSimdFunction('Float32x4 Int32x4 round trip', function() { + // NaNs should stay unmodified across bit conversions + var m = SIMD.Int32x4(0xFFFFFFFF, 0xFFFF0000, 0x80000000, 0x0); + var m2 = SIMD.Int32x4.fromFloat32x4Bits(SIMD.Float32x4.fromInt32x4Bits(m)); + equalInt32x4(m, m2); +}); diff --git a/test/built-ins/Simd/saturate.js b/test/built-ins/Simd/saturate.js new file mode 100644 index 0000000000..534cac40df --- /dev/null +++ b/test/built-ins/Simd/saturate.js @@ -0,0 +1,26 @@ +// Copyright (C) 2016 ecmascript_simd authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: saturate +description: Tests saturate methods. +includes: [simdUtilities.js] +---*/ + +simdTypes.filter(isSmallIntType).forEach(function(type) { + function saturate(type, a) { + if (a < type.minVal) return type.minVal; + if (a > type.maxVal) return type.maxVal; + return a; + } + testSimdFunction(type.name + ' addSaturate', function() { + testBinaryOp(type, 'addSaturate', function(a, b) { + return saturate(type, a + b); + }); + }); + testSimdFunction(type.name + ' subSaturate', function() { + testBinaryOp(type, 'subSaturate', function(a, b) { + return saturate(type, a - b); + }); + }); +}); diff --git a/test/built-ins/Simd/select.js b/test/built-ins/Simd/select.js new file mode 100644 index 0000000000..74ab793806 --- /dev/null +++ b/test/built-ins/Simd/select.js @@ -0,0 +1,30 @@ +// Copyright (C) 2016 ecmascript_simd authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: simd-select +description: Tests SIMD Select. +includes: [simdUtilities.js] +---*/ + +function testSelect(type) { + assert.sameValue('function', typeof type.fn.select); + // set a and b to values that are different for all numerical types. + var av = 1; + var bv = 2; + var a = type.fn.splat(av); + var b = type.fn.splat(bv); + // test all selectors with a single 'true' lane. + for (var i = 0; i < type.lanes; i++) { + var selector = type.boolType.fn(); + selector = type.boolType.fn.replaceLane(selector, i, true); + var result = type.fn.select(selector, a, b); + checkValue(type, result, function(index) { return index == i ? av : bv; }); + } +} + +simdTypes.filter(isNumerical).forEach(function(type) { + testSimdFunction(type.name + ' select', function() { + testSelect(type); + }); +}); diff --git a/test/built-ins/Simd/shift_operator.js b/test/built-ins/Simd/shift_operator.js new file mode 100644 index 0000000000..5fb9314e9a --- /dev/null +++ b/test/built-ins/Simd/shift_operator.js @@ -0,0 +1,55 @@ +// Copyright (C) 2016 ecmascript_simd authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: constructor-properties +description: Test Shift operations. +includes: [simdUtilities.js] +---*/ + +// Compare shift op's behavior to ref op at each lane. +function testShiftOp(type, op, refOp) { + assert.sameValue('function', typeof type.fn[op]); + var zero = type.fn(); + for (var v of type.interestingValues) { + var s = type.laneSize * 8; + for (var bits of [-1, 0, 1, 2, s - 1, s, s + 1]) { + var expected = simdConvert(type, refOp(simdConvert(type, v), bits)); + var a = type.fn.splat(v); + var result = type.fn[op](a, bits); + checkValue(type, result, function(index) { return expected; }); + } + } +} + +simdTypes.filter(isIntType).forEach(function(type) { + testSimdFunction(type.name + ' shiftLeftByScalar', function() { + function shift(a, bits) { + bits &= type.laneSize * 8 - 1; + return a << bits; + } + testShiftOp(type, 'shiftLeftByScalar', shift); + }); +}); + +simdTypes.filter(isSignedIntType).forEach(function(type) { + testSimdFunction(type.name + ' shiftRightByScalar', function() { + function shift(a, bits) { + bits &= type.laneSize * 8 - 1; + return a >> bits; + } + testShiftOp(type, 'shiftRightByScalar', shift); + }); +}); + +simdTypes.filter(isUnsignedIntType).forEach(function(type) { + testSimdFunction(type.name + ' shiftRightByScalar', function() { + function shift(a, bits) { + bits &= type.laneSize * 8 - 1; + if (type.laneMask) + a &= type.laneMask; + return a >>> bits; + } + testShiftOp(type, 'shiftRightByScalar', shift); + }); +}); diff --git a/test/built-ins/Simd/shuffle.js b/test/built-ins/Simd/shuffle.js new file mode 100644 index 0000000000..5b1b7069db --- /dev/null +++ b/test/built-ins/Simd/shuffle.js @@ -0,0 +1,59 @@ +// Copyright (C) 2016 ecmascript_simd authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: shuffle +description: Tests SIMD shuffle. +includes: [simdUtilities.js] +---*/ + +function testShuffle(type) { + assert.sameValue('function', typeof type.fn.shuffle); + var indices = []; + for (var i = 0; i < type.lanes; i++) indices.push(i); + + var a = type.fn.apply(type.fn, indices); // 0, 1, 2, 3, 4 ... + var b = type.fn.add(a, type.fn.splat(type.lanes)); // lanes, lanes+1 ... + // All lanes from a. + var result = type.fn.shuffle.apply(type.fn, [a, b].concat(indices)); + checkValue(type, result, function(index) { + return type.fn.extractLane(a, index); + }); + // One lane from b. + for (var i = 0; i < type.lanes; i++) { + var args = [a, b].concat(indices); + args[2 + i] += type.lanes; + var result = type.fn.shuffle.apply(type.fn, args); + checkValue(type, result, function(index) { + var val = index == i ? b : a; + return type.fn.extractLane(val, index); + }); + } + // All lanes from b. + for (var i = 0; i < type.lanes; i++) indices[i] += type.lanes; + var result = type.fn.shuffle.apply(type.fn, [a, b].concat(indices)); + checkValue(type, result, function(index) { + return type.fn.extractLane(b, index); + }); + + function testIndexCheck(index, err) { + for (var i = 0; i < type.lanes; i++) { + var args = [a, b].concat(indices); + args[i + 2] = index; + assert.throws(err, function() { type.fn.shuffle.apply(type.fn, args); }); + } + } + testIndexCheck(2 * type.lanes, RangeError); + testIndexCheck(13.37, TypeError); + testIndexCheck(undefined, TypeError); + testIndexCheck({}, TypeError); + testIndexCheck('yo', TypeError); + testIndexCheck(-1, RangeError); + testIndexCheck(128, RangeError); +} + +simdTypes.filter(isNumerical).forEach(function(type) { + testSimdFunction(type.name + ' shuffle', function() { + testShuffle(type); + }); +}); diff --git a/test/built-ins/Simd/storen.js b/test/built-ins/Simd/storen.js new file mode 100644 index 0000000000..6aebfdb073 --- /dev/null +++ b/test/built-ins/Simd/storen.js @@ -0,0 +1,86 @@ +// Copyright (C) 2016 ecmascript_simd authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: simd-store-in-tarray +description: Tests Simdstore functions. +includes: [simdUtilities.js] +---*/ + +function testStore(type, name, count) { + var storeFn = type.fn[name]; + assert.sameValue('function', typeof storeFn); + var bufLanes = 2 * type.lanes; // Test all alignments. + var bufSize = bufLanes * type.laneSize + 8; // Extra for over-alignment test. + var ab = new ArrayBuffer(bufSize); + var buf = new type.view(ab); + var a = createTestValue(type); // Value containing 0, 1, 2, 3 ... + function checkBuffer(offset) { + for (var i = 0; i < count; i++) + if (buf[offset + i] != i) return false; + return true; + } + // Test aligned stores. + for (var i = 0; i < type.lanes; i++) { + assert.sameValue(storeFn(buf, i, a), a); + assert(checkBuffer(i)); + } + // Test the 2 over-alignments. + var f64 = new Float64Array(ab); + var stride = 8 / type.laneSize; + for (var i = 0; i < 1; i++) { + assert.sameValue(storeFn(f64, i, a), a); + assert(checkBuffer(stride * i)); + } + // Test the 7 mis-alignments. + var i8 = new Int8Array(ab); + for (var misalignment = 1; misalignment < 8; misalignment++) { + assert.sameValue(storeFn(i8, misalignment, a), a); + // Shift the buffer down by misalignment. + for (var i = 0; i < i8.length - misalignment; i++) + i8[i] = i8[i + misalignment]; + assert(checkBuffer(0)); + } + + //Test index coercions + storeFn(buf, "0", a); + assert(checkBuffer(0)); + storeFn(buf, "01", a); + assert(checkBuffer(1)); + storeFn(buf, " -0.0 ", a); + assert(checkBuffer(0)); + storeFn(buf, " +1e0", a); + assert(checkBuffer(1)); + storeFn(buf, false, a); + assert(checkBuffer(0)); + storeFn(buf, true, a); + assert(checkBuffer(1)); + storeFn(buf, null, a); + assert(checkBuffer(0)); + + function testIndexCheck(buf, index, err) { + assert.throws(err, function () { storeFn(buf, index, type.fn()); }); + } + testIndexCheck(buf, -1, RangeError); + testIndexCheck(buf, bufSize / type.laneSize - count + 1, RangeError); + testIndexCheck(buf.buffer, 1, TypeError); + testIndexCheck(buf, "a", RangeError); +} + +simdTypes.filter(isNumerical).forEach(function(type) { + testSimdFunction(type.name + ' store', function() { + testStore(type, 'store', type.lanes); + }); +}); + +simdTypes.filter(hasLoadStore123).forEach(function(type) { + testSimdFunction(type.name + ' store1', function() { + testStore(type, 'store1', 1); + }); + testSimdFunction(type.name + ' store1', function() { + testStore(type, 'store2', 2); + }); + testSimdFunction(type.name + ' store3', function() { + testStore(type, 'store3', 3); + }); +}); diff --git a/test/built-ins/Simd/swizzle.js b/test/built-ins/Simd/swizzle.js new file mode 100644 index 0000000000..e6534cdb98 --- /dev/null +++ b/test/built-ins/Simd/swizzle.js @@ -0,0 +1,48 @@ +// Copyright (C) 2016 ecmascript_simd authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: swizzle +description: Tests Simd swizzle. +includes: [simdUtilities.js] +---*/ + +function testSwizzle(type) { + assert.sameValue('function', typeof type.fn.swizzle); + var a = createTestValue(type); // 0, 1, 2, 3, 4, 5, 6, ... + var indices = []; + // Identity swizzle. + for (var i = 0; i < type.lanes; i++) indices.push(i); + var result = type.fn.swizzle.apply(type.fn, [a].concat(indices)); + checkValue(type, result, function(index) { + return type.fn.extractLane(a, index); + }); + // Reverse swizzle. + indices.reverse(); + var result = type.fn.swizzle.apply(type.fn, [a].concat(indices)); + checkValue(type, result, function(index) { + return type.fn.extractLane(a, type.lanes - index - 1); + }); + + function testIndexCheck(index, err) { + for (var i = 0; i < type.lanes; i++) { + var args = [a].concat(indices); + args[i + 1] = index; + assert.throws(err, function() { type.fn.swizzle.apply(type.fn, args); }); + } + } + // RangeError + testIndexCheck(type.lanes, RangeError); + testIndexCheck(-1, RangeError); + testIndexCheck(128, RangeError); + testIndexCheck(13.37, TypeError); + testIndexCheck(undefined, TypeError); + testIndexCheck({}, TypeError); + testIndexCheck('yo', TypeError); +} + +simdTypes.filter(isNumerical).forEach(function(type) { + testSimdFunction(type.name + ' swizzle', function() { + testSwizzle(type); + }); +}); -- GitLab