VectorMask.firstTrue()/lastTrue()

Paul Sandoz paul.sandoz at oracle.com
Wed Apr 14 22:06:55 UTC 2021


Hi Remi,

That will not work because reduction with MIN will return 0 if the mask contains a false value.

You need to do something like this:

static int firstTrue(VectorMask<Integer> mask) {
    var iota = IntVector.broadcast(mask.vectorSpecies(), 0).addIndex(1);
    return IntVector.broadcast(mask.vectorSpecies(), mask.length()).blend(iota, mask).reduceLanes(VectorOperators.MIN);
}

static int lastTrue(VectorMask<Integer> mask) {
    var iota = IntVector.broadcast(mask.vectorSpecies(), 0).addIndex(1);
    return IntVector.broadcast(mask.vectorSpecies(), -1).blend(iota, mask).reduceLanes(VectorOperators.MAX);
}

I would like to add intrinsic operations for counting leading and trailing zeros (in addition to popcount), then use those operations for implementing first/lastTrue.

firstTrue == count-leading-zeros

lastTrue == length - count-trailing-zeros - 1

The above should help answer your question about the return value. But it does make me wonder if the result for "not found" is non-obvious and we should at least clarify in the Javadoc. The method names likely do not help in this regard.

Paul.


> On Apr 14, 2021, at 5:35 AM, Remi Forax <forax at univ-mlv.fr> wrote:
> 
> There is a way to implement firstTrue and lastTrue using only vector operations.
> 
> The idea is to use to mask iota with the mask and then do a reduceLanes with MIN or MAX.
> By example to for firstTrue() that returns -1 if the mask is empty,
> first create iotaPlusOne, blend with zero, then reduceLanes with MIN, then substract 1
> 
>  VectorMask mask = ...
>  var iotaPlusOne = ByteVector.broadcast(SPECIES, 1).addIndex(1);
>  ByteVector.zero(SPECIES).blend(iotaPlusOne, mask).reduceLanes(VectorOperators.MIN) - 1;
> 
> BTW, i wonder why firstTrue return the mask length instead of -1.
> 
> regards,
> Rémi



More information about the panama-dev mailing list