/**
* 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 static com.github.anba.es6draft.runtime.internal.Errors.newTypeError;
import static com.github.anba.es6draft.runtime.internal.Properties.createProperties;
import static com.github.anba.es6draft.runtime.objects.simd.SIMD.*;
import static com.github.anba.es6draft.runtime.types.Undefined.UNDEFINED;
import java.util.Arrays;
import com.github.anba.es6draft.runtime.AbstractOperations;
import com.github.anba.es6draft.runtime.ExecutionContext;
import com.github.anba.es6draft.runtime.Realm;
import com.github.anba.es6draft.runtime.internal.Initializable;
import com.github.anba.es6draft.runtime.internal.Messages;
import com.github.anba.es6draft.runtime.internal.Properties.Attributes;
import com.github.anba.es6draft.runtime.internal.Properties.Function;
import com.github.anba.es6draft.runtime.internal.Properties.Prototype;
import com.github.anba.es6draft.runtime.internal.Properties.Value;
import com.github.anba.es6draft.runtime.types.Constructor;
import com.github.anba.es6draft.runtime.types.Intrinsics;
import com.github.anba.es6draft.runtime.types.ScriptObject;
import com.github.anba.es6draft.runtime.types.builtins.BuiltinConstructor;
import com.github.anba.es6draft.runtime.types.builtins.BuiltinFunction;
/**
* <h1>SIMD</h1>
* <h2>SIMD objects</h2>
* <ul>
* <li>The SIMD.Bool64x2 Constructor
* <li>Properties of the SIMD.Bool64x2 Constructor
* </ul>
*/
public final class Bool64x2Constructor extends BuiltinConstructor implements Initializable {
private static final SIMDType SIMD_TYPE = SIMDType.Bool64x2;
@SuppressWarnings("unused")
private static final int ELEMENT_SIZE = SIMDType.Bool64x2.getElementSize();
private static final int VECTOR_LENGTH = SIMDType.Bool64x2.getVectorLength();
public Bool64x2Constructor(Realm realm) {
super(realm, SIMD_TYPE.name(), VECTOR_LENGTH);
}
@Override
public void initialize(Realm realm) {
createProperties(realm, this, Properties.class);
}
@Override
public Object call(ExecutionContext callerContext, Object thisValue, Object... args) {
ExecutionContext calleeContext = calleeContext();
Object[] fields = new Object[VECTOR_LENGTH];
for (int i = 0; i < VECTOR_LENGTH; ++i) {
fields[i] = i < args.length ? args[i] : UNDEFINED;
}
return SIMDCreateBool(calleeContext, SIMD_TYPE, fields, AbstractOperations::ToBoolean);
}
@Override
public ScriptObject construct(ExecutionContext callerContext, Constructor newTarget, Object... args) {
throw newTypeError(calleeContext(), Messages.Key.SIMDCreate, SIMD_TYPE.name());
}
@Override
protected BuiltinFunction clone() {
return new Bool64x2Constructor(getRealm());
}
/**
* Properties of the SIMD.Bool64x2 Constructor
*/
public enum Properties {
;
private static SIMDValue simdValue(ExecutionContext cx, Object value, SIMDType type) {
if (!(value instanceof SIMDValue)) {
throw newTypeError(cx, Messages.Key.IncompatibleObject);
}
if (((SIMDValue) value).getType() != type) {
throw newTypeError(cx, Messages.Key.SIMDInvalidType);
}
return (SIMDValue) value;
}
@Prototype
public static final Intrinsics __proto__ = Intrinsics.FunctionPrototype;
@Value(name = "length", attributes = @Attributes(writable = false, enumerable = false, configurable = true) )
public static final int length = VECTOR_LENGTH;
@Value(name = "name", attributes = @Attributes(writable = false, enumerable = false, configurable = true) )
public static final String name = SIMD_TYPE.name();
// FIXME: spec bug - missing definition
@Value(name = "prototype",
attributes = @Attributes(writable = false, enumerable = false, configurable = false) )
public static final Intrinsics prototype = Intrinsics.SIMD_Bool64x2Prototype;
/**
* SIMDConstructor.splat(n)
*
* @param cx
* the execution context
* @param thisValue
* the function this-value
* @param n
* the value
* @return the new SIMD value
*/
@Function(name = "splat", arity = 1)
public static Object splat(ExecutionContext cx, Object thisValue, Object n) {
/* step 1 */
Object[] list = new Object[VECTOR_LENGTH];
Arrays.fill(list, n);
/* step 2 */
return SIMDCreateBool(cx, SIMD_TYPE, list, AbstractOperations::ToBoolean);
}
/**
* SIMDConstructor.check(a)
*
* @param cx
* the execution context
* @param thisValue
* the function this-value
* @param a
* the value
* @return the SIMD value
*/
@Function(name = "check", arity = 1)
public static Object check(ExecutionContext cx, Object thisValue, Object a) {
/* steps 1-2 */
return simdValue(cx, a, SIMD_TYPE);
}
/**
* SIMDConstructor.and(a, b)
*
* @param cx
* the execution context
* @param thisValue
* the function this-value
* @param a
* the first value
* @param b
* the second value
* @return the new SIMD value
*/
@Function(name = "and", arity = 2)
public static Object and(ExecutionContext cx, Object thisValue, Object a, Object b) {
/* step 1 */
SIMDValue sa = simdValue(cx, a, SIMD_TYPE);
SIMDValue sb = simdValue(cx, b, SIMD_TYPE);
/* steps 2-3 */
SIMDValue result = SIMDBinaryOpBool(sa, sb, (x, y) -> x && y);
/* step 4 */
return result;
}
/**
* SIMDConstructor.xor(a, b)
*
* @param cx
* the execution context
* @param thisValue
* the function this-value
* @param a
* the first value
* @param b
* the second value
* @return the new SIMD value
*/
@Function(name = "xor", arity = 2)
public static Object xor(ExecutionContext cx, Object thisValue, Object a, Object b) {
/* step 1 */
SIMDValue sa = simdValue(cx, a, SIMD_TYPE);
SIMDValue sb = simdValue(cx, b, SIMD_TYPE);
/* steps 2-3 */
SIMDValue result = SIMDBinaryOpBool(sa, sb, (x, y) -> x ^ y);
/* step 4 */
return result;
}
/**
* SIMDConstructor.or(a, b)
*
* @param cx
* the execution context
* @param thisValue
* the function this-value
* @param a
* the first value
* @param b
* the second value
* @return the new SIMD value
*/
@Function(name = "or", arity = 2)
public static Object or(ExecutionContext cx, Object thisValue, Object a, Object b) {
/* step 1 */
SIMDValue sa = simdValue(cx, a, SIMD_TYPE);
SIMDValue sb = simdValue(cx, b, SIMD_TYPE);
/* steps 2-3 */
SIMDValue result = SIMDBinaryOpBool(sa, sb, (x, y) -> x | y);
/* step 4 */
return result;
}
/**
* SIMDConstructor.not(a)
*
* @param cx
* the execution context
* @param thisValue
* the function this-value
* @param a
* the value
* @return the new SIMD value
*/
@Function(name = "not", arity = 1)
public static Object not(ExecutionContext cx, Object thisValue, Object a) {
/* step 1 */
SIMDValue sa = simdValue(cx, a, SIMD_TYPE);
/* steps 2-3 */
// FIXME: spec bug - incorrect definition, should be using `!` instead of `~`
SIMDValue result = SIMDUnaryOpBool(sa, x -> !x);
/* step 4 */
return result;
}
/**
* SIMDConstructor.anyTrue(a)
*
* @param cx
* the execution context
* @param thisValue
* the function this-value
* @param a
* the value
* @return the new SIMD value
*/
@Function(name = "anyTrue", arity = 1)
public static Object anyTrue(ExecutionContext cx, Object thisValue, Object a) {
/* step 1 */
SIMDValue sa = simdValue(cx, a, SIMD_TYPE);
/* step 2 */
for (int i = 0; i < VECTOR_LENGTH; ++i) {
/* step 2.a */
if (sa.asBoolean()[i]) {
return true;
}
}
/* step 3 */
return false;
}
/**
* SIMDConstructor.allTrue(a)
*
* @param cx
* the execution context
* @param thisValue
* the function this-value
* @param a
* the value
* @return the new SIMD value
*/
@Function(name = "allTrue", arity = 1)
public static Object allTrue(ExecutionContext cx, Object thisValue, Object a) {
/* step 1 */
SIMDValue sa = simdValue(cx, a, SIMD_TYPE);
/* step 2 */
for (int i = 0; i < VECTOR_LENGTH; ++i) {
/* step 2.a */
if (!sa.asBoolean()[i]) {
return false;
}
}
/* step 3 */
return true;
}
/**
* SIMDConstructor.extractLane( simd, lane )
*
* @param cx
* the execution context
* @param thisValue
* the function this-value
* @param simd
* the simd value
* @param lane
* the lane number
* @return the SIMD lane value
*/
@Function(name = "extractLane", arity = 2)
public static Object extractLane(ExecutionContext cx, Object thisValue, Object simd, Object lane) {
/* step 1 */
SIMDValue sv = simdValue(cx, simd, SIMD_TYPE);
/* step 2 */
return SIMDExtractLaneBool(sv, SIMDToLane(cx, VECTOR_LENGTH, lane));
}
/**
* SIMDConstructor.replaceLane( simd, lane, value )
*
* @param cx
* the execution context
* @param thisValue
* the function this-value
* @param simd
* the simd value
* @param lane
* the lane number
* @param value
* the new lane value
* @return the new SIMD value
*/
@Function(name = "replaceLane", arity = 3)
public static Object replaceLane(ExecutionContext cx, Object thisValue, Object simd, Object lane,
Object value) {
/* step 1 */
SIMDValue sv = simdValue(cx, simd, SIMD_TYPE);
/* step 2 */
return SIMDReplaceLaneBool(cx, sv, lane, value, AbstractOperations::ToBoolean);
}
}
}