dart-sdk/tests/lib/typed_data/float32x4_clamp_test.dart
Ben Konyi 30f25ba735 [ VM / typed_data ] Fixed inconsistent results for -Float32x4.zero().clamp and -Float64x2.zero().clamp
The fuzzer found an issue where clamping negative zero would result in
conflicting answers depending on whether or not the clamp operation had
been optimized in JIT mode.

The MINPS and MAXPS instructions will always return the second operand
if the values being compared are -0 and 0, which is the opposite of what
the C implementation of clamp was doing.

Fixes https://github.com/dart-lang/sdk/issues/40426.

Change-Id: I3afb725bd0c8643758dbe753d863ba93c86ad747
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/134093
Reviewed-by: Alexander Markov <alexmarkov@google.com>
2020-02-03 21:59:48 +00:00

72 lines
2.2 KiB
Dart

// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// VMOptions=--optimization-counter-threshold=10 --no-background-compilation
// Library tag to be able to run in html test framework.
library float32x4_clamp_test;
import 'dart:typed_data';
import 'package:expect/expect.dart';
void testClampLowerGreaterThanUpper() {
Float32x4 l = new Float32x4(1.0, 1.0, 1.0, 1.0);
Float32x4 u = new Float32x4(-1.0, -1.0, -1.0, -1.0);
Float32x4 z = new Float32x4.zero();
Float32x4 a = z.clamp(l, u);
Expect.equals(a.x, 1.0);
Expect.equals(a.y, 1.0);
Expect.equals(a.z, 1.0);
Expect.equals(a.w, 1.0);
}
void testClamp() {
Float32x4 l = new Float32x4(-1.0, -1.0, -1.0, -1.0);
Float32x4 u = new Float32x4(1.0, 1.0, 1.0, 1.0);
Float32x4 z = new Float32x4.zero();
Float32x4 a = z.clamp(l, u);
Expect.equals(a.x, 0.0);
Expect.equals(a.y, 0.0);
Expect.equals(a.z, 0.0);
Expect.equals(a.w, 0.0);
}
Float32x4 negativeZeroClamp() {
final negZero = -Float32x4.zero();
return negZero.clamp(negZero, Float32x4.zero());
}
Float32x4 zeroClamp() {
final negOne = -Float32x4(1.0, 1.0, 1.0, 1.0);
return Float32x4.zero().clamp(negOne, -Float32x4.zero());
}
// Regression test for https://github.com/dart-lang/sdk/issues/40426.
void testNegativeZeroClamp(Float32x4 unopt) {
final res = negativeZeroClamp();
Expect.equals(res.x.compareTo(unopt.x), 0);
Expect.equals(res.y.compareTo(unopt.y), 0);
Expect.equals(res.z.compareTo(unopt.z), 0);
Expect.equals(res.w.compareTo(unopt.w), 0);
}
// Regression test for https://github.com/dart-lang/sdk/issues/40426.
void testZeroClamp(Float32x4 unopt) {
final res = zeroClamp();
Expect.equals(res.x.compareTo(unopt.x), 0);
Expect.equals(res.y.compareTo(unopt.y), 0);
Expect.equals(res.z.compareTo(unopt.z), 0);
Expect.equals(res.w.compareTo(unopt.w), 0);
}
main() {
final unoptNegZeroClamp = negativeZeroClamp();
final unoptZeroClamp = zeroClamp();
for (int i = 0; i < 2000; i++) {
testClampLowerGreaterThanUpper();
testClamp();
testNegativeZeroClamp(unoptNegZeroClamp);
testZeroClamp(unoptZeroClamp);
}
}