Covering Vector API structure and terminology 3 – Arrays, collections and data structures

0 Comments 6:42 AM

Creating vectors of same primitive value

Creating a vector and loading it up with a primitive value can be quickly accomplished via the broadcast() method as follows:

[5, 5, 5, 5, 5, 5, 5, 5]
Vector<Integer> v = VS256.broadcast(5);

The same thing can be obtained from the specialized IntVector class as well via broadcast(VectorSpecies<Integer> species, int e) or broadcast(VectorSpecies<Integer> species, long e):

IntVector v = IntVector.broadcast(VS256, 5);

Of course, we can use it to broadcast a vector of zeros as well:

[0, 0, 0, 0, 0, 0, 0 0]
Vector<Integer> v = VS256.broadcast(0);
IntVector v = IntVector.broadcast(VS256, 0);

Finally, let’s see the most common use case for creating a vector.

Creating vectors from Java arrays

Creating vectors from Java arrays is the most common use case. Practically, we start from a Java array and we call a method name fromArray().

Using fromArray() from VectorSpecies

The fromArray() method is available in VectorSpecies as fromArray(Object a, int offset). Here is an example of creating a vector from an array of integers:

int[] varr = new int[] {0, 1, 2, 3, 4, 5, 6, 7};
Vector<Integer> v = VS256.fromArray(varr, 0);

Since the varr length (8) is equal to the vector length and we start from index 0, the resulting vector will contain all the scalars from the array. This is no longer true in the following example where the last 4 scalars will not be part of the resulting vector:

int[] varr = new int[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
Vector<Integer> v = VS256.fromArray(varr, 0);

The scalars 8, 9, 10, and 11 are not present in the resulting array. Here is another example, using offset = 2:

int[] varr = new int[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
Vector<Integer> v = VS256.fromArray(varr, 2);

This time, the scalars 0, 1, 10, and 11 are not present in the resulting array.Pay attention that the length of the Java array shouldn’t be less than the vector’s length. For instance, the following example will cause an exception:

int[] varr = new int[]{0, 1, 2, 3, 4, 5};
IntVector v = IntVector.fromArray(VS256, varr, 0);

Since the Java array length is 6 (less than 8) this will cause a java.lang.IndexOutOfBoundsException. So, the minimum accepted length for varr is 8.

Using fromArray() from specialized vectors

Each specialized vector class provides a bunch of fromArray() flavors. For instance, the IntVector exposes the popular fromArray(VectorSpecies<Integer> species, int[] a, int offset) which can be used straightforward:

int[] varr = new int[] {0, 1, 2, 3, 4, 5, 6, 7};
IntVector v = IntVector.fromArray(VS256, varr, 0);

If we prefer the fromArray(VectorSpecies<Integer> species, int[] a, int offset, VectorMask<Integer> m) flavor then we can filter the selected scalars from the Java array via a VectorMask. Here is an example:

int[] varr = new int[]{0, 1, 2, 3, 4, 5, 6, 7};
boolean[] bm = new boolean[]{
  false, false, true, false, false, true, true, false};
VectorMask m = VectorMask.fromArray(VS256, bm, 0);
IntVector v = IntVector.fromArray(VS256, varr, 0, m);

Based on a one-to-one match, we can easily observe that the resulting vector will fetch only the scalars 2, 5, and 6. The resulting vector will be: [0, 0, 2, 0, 0, 5, 6, 0].Another flavor of fromArray() is fromArray(VectorSpecies<Integer> species, int[] a, int offset, int[] indexMap, int mapOffset). This time, we use a map of indexes to filter the selected scalars. For instance:

int[] varr = new int[]{11, 12, 15, 17, 20, 22, 29};
int[] imap = new int[]{0, 0, 0, 1, 1, 6, 6, 6};
IntVector v = IntVector.fromArray(VS256, varr, 0, imap, 0);

The resulting array will be: [11, 11, 11, 12, 12, 29, 29, 29]. We have 11 from index 0, 12 from index 1, and 29 from index 6.In addition, we can apply a VectorMask to the previous index map via fromArray(VectorSpecies<Integer> species, int[] a, int offset, int[] indexMap, int mapOffset, VectorMask<Integer> m):

int[] varr = new int[]{11, 12, 15, 17, 20, 22, 29};
boolean[] bm = new boolean[]{
  false, false, true, false, false, true, true, false};
int[] imap = new int[]{0, 0, 0, 1, 1, 6, 6, 6};
VectorMask m = VectorMask.fromArray(VS256, bm, 0);
IntVector v = IntVector.fromArray(VS256, varr, 0, imap, 0, m);

The resulting vector is: [0, 0, 11, 0, 0, 29, 29, 0].

Creating vectors from memory segments

Memory segments is a topic covered in detail in chapter X as part of Foreign Function & Memory API, but as a quick flash-eye, here is an example of creating a vector from a memory segment via IntVector.fromMemorySegment():

IntVector v;
MemorySegment segment;
try ( MemorySession session = MemorySession.openConfined()) {
  segment = MemorySegment.allocateNative(32, session);
  segment.setAtIndex(ValueLayout.JAVA_INT, 0, 11);
  segment.setAtIndex(ValueLayout.JAVA_INT, 1, 21);
  … continue set: 12, 7, 33, 1, 3
  segment.setAtIndex(ValueLayout.JAVA_INT, 7, 6);
  v = IntVector.fromMemorySegment(VS256, segment,
    0, ByteOrder.nativeOrder());
} The created vector is: [11, 21, 12, 7, 33, 1, 3, 6].In the bundled code you can find several more examples for manipulating data across lane boundaries such as slicing, un-slicing, shuffling/rearranging, compressing, expanding, converting, casting, and reinterpreting shape.In the next problem, we start creating complete examples that exploit what we’ve learned so far.

Leave a Reply

Your email address will not be published. Required fields are marked *