1 /*
   2  * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have
  23  * questions.
  24  */
  25 package jdk.incubator.vector;
  26 
  27 import jdk.internal.misc.Unsafe;
  28 import jdk.internal.vm.annotation.ForceInline;
  29 import java.util.function.Function;
  30 import java.util.function.IntUnaryOperator;
  31 
  32 /**
  33  * Class representing vectors of same element type, {@code E} and {@link Vector.Shape Shape}.
  34  *
  35  * @param <E> the boxed element type of this species
  36  */
  37 public abstract class Species<E> {
  38 
  39     @FunctionalInterface
  40     interface fShuffleFromArray<E> {
  41         Shuffle<E> apply(int[] reorder, int idx);
  42     }
  43 
  44     final Function<boolean[], Mask<E>> maskFactory;
  45     final Function<IntUnaryOperator, Shuffle<E>> shuffleFromOpFactory;
  46     final fShuffleFromArray<E> shuffleFromArrayFactory;
  47 
  48     Species(Function<boolean[], Mask<E>> maskFactory,
  49             Function<IntUnaryOperator, Shuffle<E>> shuffleFromOpFactory,
  50             fShuffleFromArray<E> shuffleFromArrayFactory) {
  51         this.maskFactory = maskFactory;
  52         this.shuffleFromOpFactory = shuffleFromOpFactory;
  53         this.shuffleFromArrayFactory = shuffleFromArrayFactory;
  54     }
  55 
  56     /**
  57      * Returns the primitive element type of vectors produced by this
  58      * species.
  59      *
  60      * @return the primitive element type
  61      */
  62     public abstract Class<E> elementType();
  63 
  64     /**
  65      * Returns the vector box type for this species
  66      *
  67      * @return the box type
  68      */
  69     abstract Class<?> boxType();
  70 
  71     /**
  72      * Returns the vector mask type for this species
  73      *
  74      * @return the box type
  75      */
  76     abstract Class<?> maskType();
  77 
  78     /**
  79      * Returns the element size, in bits, of vectors produced by this
  80      * species.
  81      *
  82      * @return the element size, in bits
  83      */
  84     public abstract int elementSize();
  85 
  86     /**
  87      * Returns the shape of masks, shuffles, and vectors produced by this
  88      * species.
  89      *
  90      * @return the primitive element type
  91      */
  92     public abstract Shape shape();
  93 
  94     /**
  95      * Returns the shape of the corresponding index species
  96      * @return the shape
  97      */
  98     @ForceInline
  99     public abstract Shape indexShape();
 100 
 101     /**
 102      * Returns the mask, shuffe, or vector lanes produced by this species.
 103      *
 104      * @return the the number of lanes
 105      */
 106     public int length() { return shape().length(this); }
 107 
 108     /**
 109      * Returns the total vector size, in bits, of vectors produced by this
 110      * species.
 111      *
 112      * @return the total vector size, in bits
 113      */
 114     public int bitSize() { return shape().bitSize(); }
 115 
 116     // Factory
 117 
 118     /**
 119      * Finds a species for an element type and shape.
 120      *
 121      * @param c the element type
 122      * @param s the shape
 123      * @param <E> the boxed element type
 124      * @return a species for an element type and shape
 125      * @throws IllegalArgumentException if no such species exists for the
 126      * element type and/or shape
 127      */
 128     @SuppressWarnings("unchecked")
 129     public static <E> Species<E> of(Class<E> c, Shape s) {
 130         if (c == float.class) {
 131             return (Species<E>) FloatVector.species(s);
 132         }
 133         else if (c == double.class) {
 134             return (Species<E>) DoubleVector.species(s);
 135         }
 136         else if (c == byte.class) {
 137             return (Species<E>) ByteVector.species(s);
 138         }
 139         else if (c == short.class) {
 140             return (Species<E>) ShortVector.species(s);
 141         }
 142         else if (c == int.class) {
 143             return (Species<E>) IntVector.species(s);
 144         }
 145         else if (c == long.class) {
 146             return (Species<E>) LongVector.species(s);
 147         }
 148         else {
 149             throw new IllegalArgumentException("Bad vector element type: " + c.getName());
 150         }
 151     }
 152 
 153     /**
 154      * Finds a preferred species for an element type.
 155      * <p>
 156      * A preferred species is a species chosen by the platform that has a
 157      * shape of maximal bit size.  A preferred species for different element
 158      * types will have the same shape, and therefore vectors created from
 159      * such species will be shape compatible.
 160      *
 161      * @param c the element type
 162      * @param <E> the boxed element type
 163      * @return a preferred species for an element type
 164      * @throws IllegalArgumentException if no such species exists for the
 165      * element type
 166      */
 167     public static <E> Species<E> ofPreferred(Class<E> c) {
 168         Unsafe u = Unsafe.getUnsafe();
 169 
 170         int vectorLength = u.getMaxVectorSize(c);
 171         int vectorBitSize = Vector.bitSizeForVectorLength(c, vectorLength);
 172         Shape s = Shape.forBitSize(vectorBitSize);
 173         return Species.of(c, s);
 174     }
 175 
 176     interface FOpm {
 177         boolean apply(int i);
 178     }
 179 
 180     Mask<E> opm(Species.FOpm f) {
 181         boolean[] res = new boolean[length()];
 182         for (int i = 0; i < length(); i++) {
 183             res[i] = f.apply(i);
 184         }
 185         return maskFactory.apply(res);
 186     }
 187 }
 188