Skip to content

Commit 4e33b0a

Browse files
modulovaluedart-scoped@luci-project-accounts.iam.gserviceaccount.com
authored andcommitted
[typed_data] Add Int32x4.allTrue
TEST=lib/typed_data/int32x4_compare_test Issue: #64170 Change-Id: Iae1614ebc31e494fc94561187afe6690cec8a931 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/543480 Auto-Submit: Modestas Valauskas <valauskasmodestas@gmail.com> Commit-Queue: Lasse Nielsen <lrn@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com> Reviewed-by: Stephen Adams <sra@google.com> Reviewed-by: Lasse Nielsen <lrn@google.com>
1 parent 228d92a commit 4e33b0a

7 files changed

Lines changed: 62 additions & 25 deletions

File tree

‎CHANGELOG.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
`Int32x4.anyTrue` getter, which is `true` when any lane is non-zero.
2424
- Added `Int32x4.notEqual`, a lane-wise inequality comparison that returns `-1`
2525
in each lane where the operands differ and `0` elsewhere.
26+
- Added the `Int32x4.allTrue` getter, which is `true` only when every lane is
27+
non-zero.
2628

2729
#### `dart:js_interop`
2830

‎sdk/lib/_internal/js_dev_runtime/private/native_typed_data.dart‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1749,6 +1749,8 @@ final class NativeInt32x4 implements Int32x4 {
17491749

17501750
bool get anyTrue => (x | y | z | w) != 0;
17511751

1752+
bool get allTrue => flagX && flagY && flagZ && flagW;
1753+
17521754
/// Shuffle the lane values. [mask] must be one of the 256 shuffle constants.
17531755
Int32x4 shuffle(int mask) {
17541756
if ((mask < 0) || (mask > 255)) {

‎sdk/lib/_internal/js_runtime/lib/native_typed_data.dart‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2037,6 +2037,8 @@ final class NativeInt32x4 implements Int32x4 {
20372037

20382038
bool get anyTrue => (x | y | z | w) != 0;
20392039

2040+
bool get allTrue => flagX && flagY && flagZ && flagW;
2041+
20402042
/// Shuffle the lane values. [mask] must be one of the 256 shuffle constants.
20412043
Int32x4 shuffle(int mask) {
20422044
if ((mask < 0) || (mask > 255)) {

‎sdk/lib/_internal/vm/lib/typed_data_patch.dart‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4056,6 +4056,8 @@ final class _Int32x4 implements Int32x4 {
40564056
@pragma("vm:external-name", "Int32x4_getAnyTrue")
40574057
external bool get anyTrue;
40584058

4059+
bool get allTrue => flagX && flagY && flagZ && flagW;
4060+
40594061
@pragma("vm:recognized", "other")
40604062
@pragma("vm:exact-result-type", _Int32x4)
40614063
@pragma("vm:external-name", "Int32x4_shuffle")

‎sdk/lib/_internal/wasm/common/simd.dart‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -658,6 +658,8 @@ final class I32x4 extends WasmTypedDataBase implements Int32x4 {
658658

659659
bool get anyTrue => _bits.anyTrue;
660660

661+
bool get allTrue => flagX && flagY && flagZ && flagW;
662+
661663
Int32x4 shuffle(int mask) {
662664
// mask < 0 || mask > 255
663665
RangeErrorUtils.checkValueBetweenZeroAndPositiveMax(mask, 255, 'mask');

‎sdk/lib/typed_data/typed_data.dart‎

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4406,12 +4406,22 @@ abstract final class Int32x4 {
44064406

44074407
/// Whether any of the four lanes has a non-zero value.
44084408
///
4409-
/// Returns `true` if at least one of the [x], [y], [z] or [w] lanes has any
4409+
/// Is `true` if at least one of the [x], [y], [z] or [w] lanes has any
44104410
/// bit set, and `false` only when all four lanes are zero.
44114411
///
4412-
/// Equivalent to [flagX] || [flagY] || [flagZ] || [flagW].
4412+
/// Equivalent to <code>[flagX] || [flagY] || [flagZ] || [flagW]</code>.
4413+
@Since("3.14")
44134414
bool get anyTrue;
44144415

4416+
/// Whether all four lanes have a non-zero value.
4417+
///
4418+
/// Is `true` only when every one of the [x], [y], [z] and [w] lanes has
4419+
/// at least one bit set, and `false` if any lane is zero.
4420+
///
4421+
/// Equivalent to <code>[flagX] && [flagY] && [flagZ] && [flagW]</code>.
4422+
@Since("3.14")
4423+
bool get allTrue;
4424+
44154425
/// Mask passed to [shuffle] or [shuffleMix].
44164426
static const int xxxx = 0x00;
44174427
static const int xxxy = 0x40;

‎tests/lib/typed_data/int32x4_compare_test.dart‎

Lines changed: 40 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -99,44 +99,61 @@ void testEquality(bool testingEqual) {
9999
check(Int32x4(_min, 2, _max, 4), Int32x4(0, 2, 0, 4));
100100
}
101101

102-
void testAnyTrue() {
103-
// Exhaustive over all 16 zero/non-zero lane combinations: anyTrue is true
104-
// iff at least one lane is non-zero.
105-
for (int bits = 0; bits < 16; bits++) {
106-
final v = Int32x4(
107-
(bits & 1) != 0 ? 1 : 0,
108-
(bits & 2) != 0 ? 1 : 0,
109-
(bits & 4) != 0 ? 1 : 0,
110-
(bits & 8) != 0 ? 1 : 0,
111-
);
112-
Expect.equals(bits != 0, v.anyTrue);
102+
void testAnyTrueAndAllTrue() {
103+
// For the full 16-combination matrix:
104+
// - anyTrue is true iff at least one lane is non-zero (disjunction of the
105+
// lane flags).
106+
// - allTrue is true iff every lane is non-zero (conjunction of the flags).
107+
// - a lane counts as non-zero for any set bit, so each combination is filled
108+
// from several lane-value sets, including one with a distinct bit per lane
109+
// (no bit in common) and the int32 extremes.
110+
const laneValueSets = [
111+
(1, 2, 4, 8),
112+
(-1, -1, -1, -1),
113+
(1, 2147483647, -2147483648, 8),
114+
];
115+
for (final vals in laneValueSets) {
116+
for (int bits = 0; bits < 16; bits++) {
117+
final v = Int32x4(
118+
(bits & 1) != 0 ? vals.$1 : 0,
119+
(bits & 2) != 0 ? vals.$2 : 0,
120+
(bits & 4) != 0 ? vals.$3 : 0,
121+
(bits & 8) != 0 ? vals.$4 : 0,
122+
);
123+
// Expected result: at least one lane non-zero.
124+
Expect.equals(bits != 0, v.anyTrue);
125+
// Equivalent to the disjunction of the lane flags.
126+
Expect.equals(v.flagX || v.flagY || v.flagZ || v.flagW, v.anyTrue);
127+
// Expected result: every lane non-zero.
128+
Expect.equals(bits == 0xf, v.allTrue);
129+
// Equivalent to the conjunction of the lane flags.
130+
Expect.equals(v.flagX && v.flagY && v.flagZ && v.flagW, v.allTrue);
131+
}
113132
}
114133

115-
// anyTrue is "any bit set in any lane", not "signMask != 0" (which only
116-
// checks the sign bit). Int32x4(1, 0, 0, 0) distinguishes them: it is
117-
// non-zero but the sign bit is clear, so signMask is 0 while anyTrue is true.
134+
// Both look at any set bit, not the sign bit that signMask reads. Lanes with
135+
// only low bits set have signMask 0 but are still non-zero.
118136
final lowBit = Int32x4(1, 0, 0, 0);
119137
Expect.equals(0, lowBit.signMask);
120138
Expect.isTrue(lowBit.anyTrue);
139+
Expect.isFalse(lowBit.allTrue);
121140

122-
// All lanes non-zero -> true.
123-
Expect.isTrue(Int32x4(-1, -1, -1, -1).anyTrue);
141+
final lowBits = Int32x4(1, 1, 1, 1);
142+
Expect.equals(0, lowBits.signMask);
143+
Expect.isTrue(lowBits.allTrue);
124144

125-
// Consistent with the comparison mask: a match makes anyTrue true.
145+
// Typically applied to a comparison mask.
126146
final a = Int32x4(1, 2, 3, 4);
147+
Expect.isTrue(a.equal(a).allTrue);
127148
Expect.isFalse(a.equal(Int32x4(5, 6, 7, 8)).anyTrue);
128149
Expect.isTrue(a.equal(Int32x4(0, 2, 0, 0)).anyTrue);
129-
Expect.isTrue(a.equal(a).anyTrue);
130-
131-
// Equivalent to the disjunction of the lane flags.
132-
final m = a.equal(Int32x4(0, 2, 0, 4));
133-
Expect.equals(m.flagX || m.flagY || m.flagZ || m.flagW, m.anyTrue);
150+
Expect.isFalse(a.equal(Int32x4(1, 2, 3, 0)).allTrue);
134151
}
135152

136153
void main() {
137154
for (int i = 0; i < 20; i++) {
138155
testEquality(true); // equal
139156
testEquality(false); // notEqual
140-
testAnyTrue();
157+
testAnyTrueAndAllTrue();
141158
}
142159
}

0 commit comments

Comments
 (0)