mirror of
				https://github.com/tc39/test262.git
				synced 2025-11-04 05:33:50 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			427 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			427 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
// 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;
 | 
						|
  }
 | 
						|
}
 |