/** * Copyright (c) 2012-2016 André Bargull * Alle Rechte vorbehalten / All Rights Reserved. Use is subject to license terms. * * <https://github.com/anba/es6draft> */ package com.github.anba.es6draft.runtime.objects.simd; import java.util.Arrays; import java.util.Iterator; import java.util.NoSuchElementException; import java.util.Spliterator; import java.util.Spliterators; import java.util.stream.Collectors; import java.util.stream.Stream; import java.util.stream.StreamSupport; import com.github.anba.es6draft.runtime.AbstractOperations; /** * The SIMD value. */ public final class SIMDValue { /** [[SIMDTypeDescriptor]] */ private final SIMDType type; /** [[SIMDElements]] */ private final Object elements; /** * Creates a new SIMD value. * * @param type * the SIMD type descriptor * @param elements * the SIMD elements */ /*package*/ SIMDValue(SIMDType type, Object elements) { assert elements.getClass() == classForSIMD(type); this.type = type; this.elements = elements; } private static Class<?> classForSIMD(SIMDType type) { switch (type) { case Float64x2: case Float32x4: return double[].class; case Int32x4: case Int16x8: case Int8x16: case Uint32x4: case Uint16x8: case Uint8x16: return int[].class; case Bool64x2: case Bool32x4: case Bool16x8: case Bool8x16: return boolean[].class; default: throw new AssertionError(); } } /** * [[SIMDTypeDescriptor]] * * @return the SIMD type descriptor */ public SIMDType getType() { return type; } /** * [[SIMDElements]] * * @return the SIMD elements */ public Object getElements() { return elements; } /** * Returns the SIMD elements as a {@code double[]} array. * * @return the SIMD elements * @throws ClassCastException * if SIMD type is not a floating point type */ public double[] asDouble() { return (double[]) elements; } /** * Returns the SIMD elements as an {@code int[]} array. * * @return the SIMD elements * @throws ClassCastException * if SIMD type is not an integer type */ public int[] asInt() { return (int[]) elements; } /** * Returns the SIMD elements as a {@code boolean[]} array. * * @return the SIMD elements * @throws ClassCastException * if SIMD type is not a boolean type */ public boolean[] asBoolean() { return (boolean[]) elements; } @Override public boolean equals(Object obj) { // equals() implements SameValue semantics. if (this == obj) { return true; } if (obj == null || obj.getClass() != SIMDValue.class) { return false; } SIMDValue other = (SIMDValue) obj; if (type != other.type) { return false; } if (elements instanceof double[]) { return Arrays.equals((double[]) elements, (double[]) other.elements); } if (elements instanceof int[]) { return Arrays.equals((int[]) elements, (int[]) other.elements); } return Arrays.equals((boolean[]) elements, (boolean[]) other.elements); } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + type.hashCode(); if (elements instanceof double[]) { result = prime * result + Arrays.hashCode((double[]) elements); } else if (elements instanceof int[]) { result = prime * result + Arrays.hashCode((int[]) elements); } else { result = prime * result + Arrays.hashCode((boolean[]) elements); } return result; } @Override public String toString() { // String representation per SIMD ToString() specification. Stream<String> content; switch (type) { case Float64x2: case Float32x4: content = Arrays.stream((double[]) elements).mapToObj(AbstractOperations::ToString); break; case Int32x4: case Int16x8: case Int8x16: case Uint16x8: case Uint8x16: content = Arrays.stream((int[]) elements).mapToObj(AbstractOperations::ToString); break; case Uint32x4: content = Arrays.stream((int[]) elements).mapToLong(Integer::toUnsignedLong) .mapToObj(AbstractOperations::ToString); break; case Bool64x2: case Bool32x4: case Bool16x8: case Bool8x16: content = booleanStream((boolean[]) elements).map(b -> Boolean.toString(b)); break; default: throw new AssertionError(); } return content.collect(Collectors.joining(", ", "SIMD." + type.name() + "(", ")")); } private static Stream<Boolean> booleanStream(boolean[] array) { Spliterator<Boolean> spliterator = Spliterators.spliterator(new Iterator<Boolean>() { int index = 0; @Override public boolean hasNext() { return index < array.length; } @Override public Boolean next() { if (index >= array.length) { throw new NoSuchElementException(); } return array[index++]; } }, array.length, Spliterator.ORDERED | Spliterator.IMMUTABLE); return StreamSupport.stream(spliterator, false); } }