All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.openhft.hashing.Maths Maven / Gradle / Ivy

package net.openhft.hashing;

import org.jetbrains.annotations.NotNull;

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Method;

class Maths {
    @NotNull
    private static final Maths INSTANCE;

    static {
        Maths maths = null;
        try {
            Method multiplyHigh = Math.class.getDeclaredMethod("multiplyHigh", int.class, int.class);
            MethodHandle multiplyHighMH = MethodHandles.lookup().unreflect(multiplyHigh);
            maths = new MathsJDK9(multiplyHighMH);
        } catch (final Throwable ignore) {
            maths = new Maths();
        }
        INSTANCE = maths;
    }

    public static long unsignedLongMulXorFold(final long lhs, final long rhs) {
        return INSTANCE.unsignedLongMulXorFoldImp(lhs, rhs);
    }
    public static long unsignedLongMulHigh(final long lhs, final long rhs) {
        return INSTANCE.unsignedLongMulHighImp(lhs, rhs);
    }

    long unsignedLongMulXorFoldImp(final long lhs, final long rhs) {
        // The Grade School method of multiplication is a hair faster in Java, primarily used here
        // because the implementation is simpler.
        final long lhs_l = lhs & 0xFFFFFFFFL;
        final long lhs_h = lhs >>> 32;
        final long rhs_l = rhs & 0xFFFFFFFFL;
        final long rhs_h = rhs >>> 32;
        final long lo_lo = lhs_l * rhs_l;
        final long hi_lo = lhs_h * rhs_l;
        final long lo_hi = lhs_l * rhs_h;
        final long hi_hi = lhs_h * rhs_h;

        // Add the products together. This will never overflow.
        final long cross = (lo_lo >>> 32) + (hi_lo & 0xFFFFFFFFL) + lo_hi;
        final long upper = (hi_lo >>> 32) + (cross >>> 32) + hi_hi;
        final long lower = (cross << 32) | (lo_lo & 0xFFFFFFFFL);
        return lower ^ upper;
    }

    long unsignedLongMulHighImp(final long lhs, final long rhs) {
        // The Grade School method of multiplication is a hair faster in Java, primarily used here
        // because the implementation is simpler.
        final long lhs_l = lhs & 0xFFFFFFFFL;
        final long lhs_h = lhs >>> 32;
        final long rhs_l = rhs & 0xFFFFFFFFL;
        final long rhs_h = rhs >>> 32;
        final long lo_lo = lhs_l * rhs_l;
        final long hi_lo = lhs_h * rhs_l;
        final long lo_hi = lhs_l * rhs_h;
        final long hi_hi = lhs_h * rhs_h;

        // Add the products together. This will never overflow.
        final long cross = (lo_lo >>> 32) + (hi_lo & 0xFFFFFFFFL) + lo_hi;
        final long upper = (hi_lo >>> 32) + (cross >>> 32) + hi_hi;
        return upper;
    }
}

class MathsJDK9 extends Maths {
    private final MethodHandle multiplyHighMH;

    public MathsJDK9(MethodHandle multiplyHighMH) {
        this.multiplyHighMH = multiplyHighMH;
    }

    // Math.multiplyHigh() is intrinsified from JDK 10. But JDK 9 is out of life, we always prefer
    // this version to the scalar one.
    @Override
    long unsignedLongMulXorFoldImp(final long lhs, final long rhs) {
        final long upper = invokeExact(lhs, rhs) + ((lhs >> 63) & rhs) + ((rhs >> 63) & lhs);
        final long lower = lhs * rhs;
        return lower ^ upper;
    }
    @Override
    long unsignedLongMulHighImp(final long lhs, final long rhs) {
        return invokeExact(lhs, rhs) + ((lhs >> 63) & rhs) + ((rhs >> 63) & lhs);
    }

    private long invokeExact(long lhs, long rhs) {
        try {
            return (long) multiplyHighMH.invokeExact(lhs, rhs);
        } catch (Throwable e) {
            throw new AssertionError(e);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy