Skip to content
This repository has been archived by the owner on Feb 16, 2018. It is now read-only.

Commit

Permalink
Implement new min/max semantics
Browse files Browse the repository at this point in the history
Following the proposal in
tc39#67

These min and max functions follow the Math.min and Math.max semantics,
and are arguably the more intuitive and semantics.

This patch also introduces minNum and maxNum functions, which follow the
IEEE-754 minNum and maxNum semantics.
  • Loading branch information
sunfishcode committed Oct 20, 2014
1 parent 60386dc commit 2015cf3
Show file tree
Hide file tree
Showing 2 changed files with 122 additions and 12 deletions.
88 changes: 76 additions & 12 deletions src/ecmascript_simd.js
Expand Up @@ -46,6 +46,18 @@ _PRIVATE.truncatei32 = function(x) {
return _PRIVATE._i32[0];
}

_PRIVATE.minNum = function(x, y) {
return x != x ? y :
y != y ? x :
Math.min(x, y);
}

_PRIVATE.maxNum = function(x, y) {
return x != x ? y :
y != y ? x :
Math.max(x, y);
}

function checkFloat32x4(t) {
if (!(t instanceof SIMD.float32x4)) {
throw new TypeError("argument is not a float32x4.");
Expand Down Expand Up @@ -437,10 +449,10 @@ SIMD.float32x4.clamp = function(t, lowerLimit, upperLimit) {
SIMD.float32x4.min = function(t, other) {
checkFloat32x4(t);
checkFloat32x4(other);
var cx = t.x > other.x ? other.x : t.x;
var cy = t.y > other.y ? other.y : t.y;
var cz = t.z > other.z ? other.z : t.z;
var cw = t.w > other.w ? other.w : t.w;
var cx = Math.min(t.x, other.x);
var cy = Math.min(t.y, other.y);
var cz = Math.min(t.z, other.z);
var cw = Math.min(t.w, other.w);
return SIMD.float32x4(cx, cy, cz, cw);
}

Expand All @@ -451,10 +463,38 @@ SIMD.float32x4.min = function(t, other) {
SIMD.float32x4.max = function(t, other) {
checkFloat32x4(t);
checkFloat32x4(other);
var cx = t.x < other.x ? other.x : t.x;
var cy = t.y < other.y ? other.y : t.y;
var cz = t.z < other.z ? other.z : t.z;
var cw = t.w < other.w ? other.w : t.w;
var cx = Math.max(t.x, other.x);
var cy = Math.max(t.y, other.y);
var cz = Math.max(t.z, other.z);
var cw = Math.max(t.w, other.w);
return SIMD.float32x4(cx, cy, cz, cw);
}

/**
* @return {float32x4} New instance of float32x4 with the minimum value of
* t and other, preferring numbers over NaNs.
*/
SIMD.float32x4.minNum = function(t, other) {
checkFloat32x4(t);
checkFloat32x4(other);
var cx = _PRIVATE.minNum(t.x, other.x);
var cy = _PRIVATE.minNum(t.y, other.y);
var cz = _PRIVATE.minNum(t.z, other.z);
var cw = _PRIVATE.minNum(t.w, other.w);
return SIMD.float32x4(cx, cy, cz, cw);
}

/**
* @return {float32x4} New instance of float32x4 with the maximum value of
* t and other, preferring numbers over NaNs.
*/
SIMD.float32x4.maxNum = function(t, other) {
checkFloat32x4(t);
checkFloat32x4(other);
var cx = _PRIVATE.maxNum(t.x, other.x);
var cy = _PRIVATE.maxNum(t.y, other.y);
var cz = _PRIVATE.maxNum(t.z, other.z);
var cw = _PRIVATE.maxNum(t.w, other.w);
return SIMD.float32x4(cx, cy, cz, cw);
}

Expand Down Expand Up @@ -965,8 +1005,8 @@ SIMD.float64x2.clamp = function(t, lowerLimit, upperLimit) {
SIMD.float64x2.min = function(t, other) {
checkFloat64x2(t);
checkFloat64x2(other);
var cx = t.x > other.x ? other.x : t.x;
var cy = t.y > other.y ? other.y : t.y;
var cx = Math.min(t.x, other.x);
var cy = Math.min(t.y, other.y);
return SIMD.float64x2(cx, cy);
}

Expand All @@ -977,8 +1017,32 @@ SIMD.float64x2.min = function(t, other) {
SIMD.float64x2.max = function(t, other) {
checkFloat64x2(t);
checkFloat64x2(other);
var cx = t.x < other.x ? other.x : t.x;
var cy = t.y < other.y ? other.y : t.y;
var cx = Math.max(t.x, other.x);
var cy = Math.max(t.y, other.y);
return SIMD.float64x2(cx, cy);
}

/**
* @return {float64x2} New instance of float64x2 with the minimum value of
* t and other, preferring numbers over NaNs.
*/
SIMD.float64x2.minNum = function(t, other) {
checkFloat64x2(t);
checkFloat64x2(other);
var cx = _PRIVATE.minNum(t.x > other.x);
var cy = _PRIVATE.minNum(t.y > other.y);
return SIMD.float64x2(cx, cy);
}

/**
* @return {float64x2} New instance of float64x2 with the maximum value of
* t and other, preferring numbers over NaNs.
*/
SIMD.float64x2.maxNum = function(t, other) {
checkFloat64x2(t);
checkFloat64x2(other);
var cx = _PRIVATE.maxNum(t.x, other.x);
var cy = _PRIVATE.maxNum(t.y, other.y);
return SIMD.float64x2(cx, cy);
}

Expand Down
46 changes: 46 additions & 0 deletions src/ecmascript_simd_tests.js
Expand Up @@ -222,6 +222,16 @@ test('float32x4 min', function() {
equal(1.0, c.y);
equal(30.0, c.z);
equal(0.0, c.w);

var x = SIMD.float32x4(-0, 0, NaN, 0);
var y = SIMD.float32x4(0, -0, 0, NaN);
var z = SIMD.float32x4.min(x, y);
equal(0, z.x);
equal(1 / z.x, -Infinity);
equal(0, z.y);
equal(1 / z.y, -Infinity);
notEqual(z.z, z.z);
notEqual(z.w, z.w);
});

test('float32x4 min exceptions', function() {
Expand All @@ -243,6 +253,16 @@ test('float32x4 max', function() {
equal(10.0, c.y);
equal(55.0, c.z);
equal(1.0, c.w);

var x = SIMD.float32x4(-0, 0, NaN, 0);
var y = SIMD.float32x4(0, -0, 0, NaN);
var z = SIMD.float32x4.max(x, y);
equal(0, z.x);
equal(1 / z.x, Infinity);
equal(0, z.y);
equal(1 / z.y, Infinity);
notEqual(z.z, z.z);
notEqual(z.w, z.w);
});

test('float32x4 max exceptions', function() {
Expand Down Expand Up @@ -843,6 +863,19 @@ test('float64x2 min', function() {
var c = SIMD.float64x2.min(a, lower);
equal(-20.0, c.x);
equal(1.0, c.y);

var x = SIMD.float64x2(-0, 0);
var y = SIMD.float64x2(0, -0);
var z = SIMD.float64x2.min(x, y);
equal(0, z.x);
equal(1 / z.x, -Infinity);
equal(0, z.y);
equal(1 / z.y, -Infinity);
x = SIMD.float64x2(NaN, 0);
y = SIMD.float64x2(0, NaN);
z = SIMD.float64x2.min(x, y);
notEqual(z.x, z.x);
notEqual(z.y, z.y);
});

test('float64x2 min exceptions', function() {
Expand All @@ -862,6 +895,19 @@ test('float64x2 max', function() {
var c = SIMD.float64x2.max(a, upper);
equal(2.5, c.x);
equal(10.0, c.y);

var x = SIMD.float64x2(-0, 0);
var y = SIMD.float64x2(0, -0);
var z = SIMD.float64x2.max(x, y);
equal(0, z.x);
equal(1 / z.x, Infinity);
equal(0, z.y);
equal(1 / z.y, Infinity);
x = SIMD.float64x2(NaN, 0);
y = SIMD.float64x2(0, NaN);
z = SIMD.float64x2.max(x, y);
notEqual(z.x, z.x);
notEqual(z.y, z.y);
});

test('float64x2 max exceptions', function() {
Expand Down

0 comments on commit 2015cf3

Please sign in to comment.