Comment #0 by bearophile_hugs — 2014-06-06T17:18:27Z
Value equality is quite important for the usability of a type. This code is currently refused:
void main() {
import core.simd: int4;
import std.algorithm: uniq;
int4[] data = [[1, 2, 3, 4], [1, 2, 3, 4], [10, 20, 30, 40]];
data.uniq;
}
dmd 2.066alpha gives:
test.d(5): Error: template std.algorithm.uniq does not match any function template declaration. Candidates are:
...\ldc2\bin/../import\std\algorithm.d(3346): std.algorithm.uniq(alias pred = "a == b", Range)(Range r) if (isInputRange!Range && is(typeof(binaryFun!pred(r.front, r.front)) == bool))
test.d(5): Error: template std.algorithm.uniq(alias pred = "a == b", Range)(Range r) if (isInputRange!Range && is(typeof(binaryFun!pred(r.front, r.front)) == bool)) cannot deduce template function from argument types !()(__vector(int[4])[])
A workaround is to call .array, but this is quite inefficient code:
void main() {
import core.simd: int4;
import std.algorithm: uniq;
int4[] data = [[1, 2, 3, 4], [1, 2, 3, 4], [10, 20, 30, 40]];
data.uniq!q{ a.array == b.array };
}
There are two different possible equalities among SIMD values: the first returns a bool normally, and the second returns a SIMD value that contains N booleans represented as zero/notzero values. The first can be computed with a xor followed by a sum + shuffle + sum + shuffle ... for log2(N) cycles.
I think the first equality operation should be built-in.
An alternative is to have a function like this but I think it's not a large improvement because it has to perform the same operations as a built-in equality:
void main() {
import core.simd: int4;
import std.algorithm: uniq;
int4[] data = [[1, 2, 3, 4], [1, 2, 3, 4], [10, 20, 30, 40]];
data.uniq!q{ simdEquality(a, b) };
}
But such simdEquality function is OK for the second kind of SIMD equality, that returns a SIMD of booleans.
Comment #1 by robert.schadek — 2024-12-13T18:21:19Z