com.carrotsearch.hppc.Intrinsics Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of hppc-template-processor Show documentation
Show all versions of hppc-template-processor Show documentation
Template Processor and Code Generation for HPPC.
The newest version!
package com.carrotsearch.hppc;
import java.util.Objects;
/**
* Intrinsic methods that are fully functional for the source templates
* (generic) and are replaced with low-level corresponding equivalents for the
* generated primitive types.
*
* Whenever there is a generic type on a static method it can be used to parameterize
* the given method based on the actual template type. Most intrinsics can guess their
* generic template parameter (for example if the template has only one replaceable
* type), but sometimes it may be necessary to provide the template type directly.
*
* This class should not appear in the final distribution (all methods are
* replaced in templates. Use forbidden-apis checker to make sure this is the
* case.
*/
public final class Intrinsics {
/**
* Anything that implements value-equality function as replaced by the
* {@link #equals} intrinsic.
*
* Not a public interface because we want the implementing methods to be
* effectively protected, but used for API consistency in templates.
*/
public interface EqualityFunction {
boolean equals(Object v1, Object v2);
}
/**
* Anything that distributes keys by their hash value.
*
* Not a public interface because we want the implementing methods to be
* effectively protected, but used for API consistency in templates. *
*/
public interface KeyHasher {
int hashKey(T key);
}
/**
* Everything static.
*/
private Intrinsics() {}
/**
* Returns true
if the provided value is an "empty key" marker.
* For generic types the empty key is null
, for any other type
* it is an equivalent of zero.
*
* Testing for zeros should be compiled into fast machine code.
*/
public static boolean isEmpty(Object value) {
return value == null;
}
/**
* Returns the default "empty key" (null
or 0
for
* primitive types).
*/
public static T empty() {
return (T) null;
}
/**
* A template cast to the given type T. With type erasure it should work
* internally just fine and it simplifies code. The cast will be erased for
* primitive types.
*/
@SuppressWarnings("unchecked")
public static T cast(Object value) {
return (T) value;
}
/**
* Creates an array for the given template type.
*/
@SuppressWarnings("unchecked")
public static T[] newArray(int arraySize) {
return (T[]) new Object[arraySize];
}
/**
* Compare two keys for equivalence.
*
* Generic types are compared using the delegate function.
*
* Primitive types are compared using ==
, except for
* floating-point types where they're compared by their actual representation
* bits as returned from {@link Double#doubleToLongBits(double)} and
* {@link Float#floatToIntBits(float)}.
*/
public static boolean equals(EqualityFunction delegate, Object e1, Object e2) {
return delegate.equals(e1, e2);
}
/**
* Compare two keys for equivalence.
*
* Generic types are compared for null-equivalence or using
* {@link Object#equals(Object)}.
*
* Primitive types are compared using ==
, except for
* floating-point types where they're compared by their actual representation
* bits as returned from {@link Double#doubleToLongBits(double)} and
* {@link Float#floatToIntBits(float)}.
*/
public static boolean equals(Object e1, Object e2) {
return Objects.equals(e1, e2);
}
/**
* An intrinsic that is replaced with plain addition of arguments for
* primitive template types. Invalid for non-number generic types.
*/
@SuppressWarnings("unchecked")
public static T add(T op1, T op2) {
if (op1.getClass() != op2.getClass()) {
throw new RuntimeException("Arguments of different classes: " + op1 + " " + op2);
}
if (Byte.class.isInstance(op1)) {
return (T)(Byte)(byte)(((Byte) op1).byteValue() + ((Byte) op2).byteValue());
}
if (Short.class.isInstance(op1)) {
return (T)(Short)(short)(((Short) op1).shortValue() + ((Short) op2).shortValue());
}
if (Character.class.isInstance(op1)) {
return (T)(Character)(char)(((Character) op1).charValue() + ((Character) op2).charValue());
}
if (Integer.class.isInstance(op1)) {
return (T)(Integer)(((Integer) op1).intValue() + ((Integer) op2).intValue());
}
if (Float.class.isInstance(op1)) {
return (T)(Float)(((Float) op1).floatValue() + ((Float) op2).floatValue());
}
if (Long.class.isInstance(op1)) {
return (T)(Long)(((Long) op1).longValue() + ((Long) op2).longValue());
}
if (Double.class.isInstance(op1)) {
return (T)(Double)(((Double) op1).doubleValue() + ((Double) op2).doubleValue());
}
throw new UnsupportedOperationException("Invalid for arbitrary types: " + op1 + " " + op2);
}
}