Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright (c) 2022-2023 See AUTHORS file.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.github.tommyettinger.digital;
/**
* Methods for converting floats to and from ints, as well as doubles to and from longs and ints.
* This is like NumberUtils in libGDX, but is closer to a subset of NumberTools in SquidLib. It
* includes methods like {@link #floatToReversedIntBits(float)} (which is also in NumberTools, and
* makes converting from an OpenGL packed ABGR float to an RGBA8888 int very easy) and
* {@link #doubleToMixedIntBits(double)} (which is useful when implementing hashCode() for double
* values). Everything's optimized for GWT, which is important because some core JDK methods like
* {@link Float#floatToIntBits(float)} are quite slow on GWT. This makes heavy use of JS typed
* arrays to accomplish its conversions; these are widespread even on mobile browsers, and are very
* convenient for this sort of code (in some ways, they're a better fit for this sort of bit-level
* operation in JavaScript than anything Java provides).
*
* @author Tommy Ettinger
*/
public final class BitConversion {
/**
* No need to instantiate.
*/
private BitConversion() {
}
/**
* Identical to {@link Double#doubleToLongBits(double)} on desktop; optimized on GWT. When compiling to JS via GWT,
* there is no way to distinguish NaN values with different bits but that are still NaN, so this doesn't try to
* somehow permit that. Uses JS typed arrays on GWT, which are well-supported now across all recent browsers and
* have fallbacks in GWT in the unlikely event of a browser not supporting them. JS typed arrays support double, but
* not long, so this needs to compose a long from two ints, which means the double-to/from-long conversions aren't
* as fast as float-to/from-int conversions.
*
* This method may be a tiny bit slower than {@link #doubleToRawLongBits(double)} on non-HotSpot JVMs.
*
* @param value a {@code double} floating-point number.
* @return the bits that represent the floating-point number.
*/
public static long doubleToLongBits(final double value) {
return Double.doubleToLongBits(value);
}
/**
* Identical to {@link Double#doubleToRawLongBits(double)} on desktop; optimized on GWT. When compiling to JS via
* GWT, there is no way to distinguish NaN values with different bits but that are still NaN, so this doesn't try
* to somehow permit that. Uses JS typed arrays on GWT, which are well-supported now across all recent browsers and
* have fallbacks in GWT in the unlikely event of a browser not supporting them. JS typed arrays support double, but
* not long, so this needs to compose a long from two ints, which means the double-to/from-long conversions aren't
* as fast as float-to/from-int conversions on GWT. Note that on GWT, the "Raw" conversions aren't available in
* Double or Float, and the versions here are identical to the "non-Raw" versions on GWT.
*
* @param value a {@code double} floating-point number.
* @return the bits that represent the floating-point number.
*/
public static long doubleToRawLongBits(final double value) {
return Double.doubleToRawLongBits(value);
}
/**
* Gets the bit representation of the given double {@code value}, but with reversed byte order. On desktop, this is
* equivalent to calling {@code Long.reverseBytes(Double.doubleToRawLongBits(value))}, but it is implemented using
* typed arrays on GWT. Note that this reverses byte order, not bit order.
*
* This method runs at the expected speed on desktop and mobile, where it should compile down to two (very fast)
* intrinsics, but GWT should run it much more quickly than a direct translation of the Java would provide.
*
* @param value any double
* @return the bits that represent the floating-point value, with their byte order reversed from normal.
*/
public static long doubleToReversedLongBits(final double value) {
return Long.reverseBytes(Double.doubleToRawLongBits(value));
}
/**
* Reverses the byte order of {@code bits} and converts that to a double. On desktop, this is equivalent to calling
* {@code Double.longBitsToDouble(Long.reverseBytes(bits))}, but it is implemented using typed arrays on GWT. Note
* that this reverses byte order, not bit order.
*
* This method runs at the expected speed on desktop and mobile, where it should compile down to two (very fast)
* intrinsics, but GWT should run it much more quickly than a direct translation of the Java would provide.
*
* @param bits a long
* @return the {@code double} floating-point value with the given bits using their byte order reversed from normal.
*/
public static double reversedLongBitsToDouble(final long bits) {
return Double.longBitsToDouble(Long.reverseBytes(bits));
}
/**
* Identical to {@link Double#longBitsToDouble(long)} on desktop; optimized on GWT. Uses JS typed arrays on GWT,
* which are well-supported now across all recent browsers and have fallbacks in GWT in the unlikely event of a
* browser not supporting them. JS typed arrays support double, but not long, so this needs to compose a long from
* two ints, which means the double-to/from-long conversions aren't as fast as float-to/from-int conversions.
*
* @param bits a long.
* @return the {@code double} floating-point value with the same bit pattern.
*/
public static double longBitsToDouble(final long bits) {
return Double.longBitsToDouble(bits);
}
/**
* Converts the raw bits of {@code value} to a long and gets the lower 32 bits of that long, as an int. This
* performs better on GWT than casting the result of {@link #doubleToRawLongBits(double)} to int, because it doesn't
* create a {@code long} internally on that platform, and longs are quite slow on GWT.
*
* @param value a {@code double} precision floating-point number.
* @return the lower half of the bits that represent the floating-point number, as an int.
*/
public static int doubleToLowIntBits(final double value) {
return (int) Double.doubleToRawLongBits(value);
}
/**
* Converts the raw bits of {@code value} to a long and gets the upper 32 bits of that long, as an int. This
* performs better on GWT than casting the result of {@link #doubleToRawLongBits(double)} to int, because it doesn't
* create a {@code long} internally on that platform, and longs are quite slow on GWT.
*
* @param value a {@code double} precision floating-point number.
* @return the upper half of the bits that represent the floating-point number, as an int.
*/
public static int doubleToHighIntBits(final double value) {
return (int) (Double.doubleToRawLongBits(value) >>> 32);
}
/**
* Converts the bits of {@code value} to a long and gets the XOR of its upper and lower 32-bit sections. Useful for
* numerical code where a 64-bit double needs to be reduced to a 32-bit value with some hope of keeping different
* doubles giving different ints. This performs better on GWT than working with {@link #doubleToRawLongBits(double)}
* and XORing its upper and lower halves, because it doesn't create a {@code long} internally on that platform, and
* longs are quite slow on GWT.
*
* @param value a {@code double} precision floating-point number.
* @return the XOR of the lower and upper halves of the bits that represent the floating-point number.
*/
public static int doubleToMixedIntBits(final double value) {
final long l = Double.doubleToRawLongBits(value);
return (int) (l ^ l >>> 32);
}
/**
* Identical to {@link Float#floatToIntBits(float)} on desktop; optimized on GWT. Uses JS typed arrays on GWT, which
* are well-supported now across all recent browsers and have fallbacks in GWT in the unlikely event of a browser
* not supporting them.
*
* This method may be a tiny bit slower than {@link #floatToRawIntBits(float)} on non-HotSpot JVMs.
*
* @param value a floating-point number.
* @return the bits that represent the floating-point number.
*/
public static int floatToIntBits(final float value) {
return Float.floatToIntBits(value);
}
/**
* Identical to {@link Float#floatToRawIntBits(float)} on desktop; optimized on GWT. When compiling to JS via GWT,
* there is no way to distinguish NaN values with different bits but that are still NaN, so this doesn't try to
* somehow permit that. Uses JS typed arrays on GWT, which are well-supported now across all recent browsers and
* have fallbacks in GWT in the unlikely event of a browser not supporting them. Note that on GWT, the "Raw"
* conversions aren't available in Double or Float, and the versions here are identical to the "non-Raw" versions on
* GWT.
*
* @param value a floating-point number.
* @return the bits that represent the floating-point number.
*/
public static int floatToRawIntBits(final float value) {
return Float.floatToRawIntBits(value);
}
/**
* Gets the bit representation of the given float {@code value}, but with reversed byte order. On desktop, this is
* equivalent to calling {@code Integer.reverseBytes(Float.floatToRawIntBits(value))}, but it is implemented using
* typed arrays on GWT. Note that this reverses byte order, not bit order.
*
* This is primarily intended for a common task in libGDX's internals: converting between RGBA8888 int colors and
* ABGR packed float colors. This method runs at the expected speed on desktop and mobile, where it should compile
* down to two (very fast) intrinsics, but GWT should run it much more quickly than a direct translation of the Java
* would provide.
*
* @param value a floating-point number
* @return the bits that represent the floating-point number, with their byte order reversed from normal.
*/
public static int floatToReversedIntBits(final float value) {
return Integer.reverseBytes(Float.floatToRawIntBits(value));
}
/**
* Reverses the byte order of {@code bits} and converts that to a float. On desktop, this is
* equivalent to calling {@code Float.intBitsToFloat(Integer.reverseBytes(bits))}, but it is implemented using
* typed arrays on GWT. Note that this reverses byte order, not bit order.
*
* This is primarily intended for a common task in libGDX's internals: converting between RGBA8888 int colors and
* ABGR packed float colors. This method runs at the expected speed on desktop and mobile, where it should compile
* down to two (very fast) intrinsics, but GWT should run it much more quickly than a direct translation of the Java
* would provide.
*
* @param bits an integer
* @return the {@code float} floating-point value with the given bits using their byte order reversed from normal.
*/
public static float reversedIntBitsToFloat(final int bits) {
return Float.intBitsToFloat(Integer.reverseBytes(bits));
}
/**
* Identical to {@link Float#intBitsToFloat(int)} on desktop; optimized on GWT. Uses JS typed arrays on GWT, which
* are well-supported now across all recent browsers and have fallbacks in GWT in the unlikely event of a browser
* not supporting them.
*
* @param bits an integer.
* @return the {@code float} floating-point value with the same bit pattern.
*/
public static float intBitsToFloat(final int bits) {
return Float.intBitsToFloat(bits);
}
/**
* Returns an int value with at most a single one-bit, in the position of the lowest-order ("rightmost") one-bit in
* the specified int value. Returns zero if the specified value has no one-bits in its two's complement binary
* representation, that is, if it is equal to zero.
*
* Identical to {@link Integer#lowestOneBit(int)}, including on GWT. GWT calculates Integer.lowestOneBit() correctly,
* but does not always calculate Long.lowestOneBit() correctly. This overload is here so you can use lowestOneBit on
* an int value and get an int value back (which could be assigned to a long without losing data), or use it on a
* long value and get the correct long result on both GWT and other platforms.
*
* @param num the value whose lowest one bit is to be computed
* @return an int value with a single one-bit, in the position of the lowest-order one-bit in the specified value,
* or zero if the specified value is itself equal to zero.
*/
public static int lowestOneBit(int num) {
return num & -num;
}
/**
* Returns an long value with at most a single one-bit, in the position of the lowest-order ("rightmost") one-bit in
* the specified long value. Returns zero if the specified value has no one-bits in its two's complement binary
* representation, that is, if it is equal to zero.
*
* Identical to {@link Long#lowestOneBit(long)}, but super-sourced to act correctly on GWT. At least on GWT 2.8.2,
* {@link Long#lowestOneBit(long)} does not provide correct results for certain inputs on GWT. For example, when given
* -17592186044416L, Long.lowestOneBit() returns 0 on GWT, possibly because it converts to an int at some point. On
* other platforms, like desktop JDKs, {@code Long.lowestOneBit(-17592186044416L)} returns 17592186044416L.
*
* @param num the value whose lowest one bit is to be computed
* @return a long value with a single one-bit, in the position of the lowest-order one-bit in the specified value,
* or zero if the specified value is itself equal to zero.
*/
public static long lowestOneBit(long num) {
return num & -num;
}
/**
* 32-bit signed integer multiplication that is correct on all platforms, including GWT. Unlike desktop, Android,
* and iOS targets, GWT uses the equivalent of a {@code double} to represent an {@code int}, which means any
* multiplication where the product is large enough (over 2 to the 53) can start to lose precision instead of being
* wrapped, like it would on overflow in a normal JDK. Using this will prevent the possibility of precision loss.
*
* This should compile down to a call to {@code Math.imul()} on GWT, hence the name here.
* @param left the multiplicand
* @param right the multiplier
* @return the product of left times right, wrapping on overflow as is normal for Java
*/
public static int imul(int left, int right) {
return left * right;
}
/**
* Returns the unbiased exponent used in the representation of a float. This delegates to
* {@link Math#getExponent(float)} on most platforms, but on GWT it uses a super-sourced implementation.
* @param num any float
* @return the unbiased exponent of num, from {@link Float#MIN_EXPONENT} - 1 to {@link Float#MAX_EXPONENT} + 1
*/
public static int getExponent(float num) {
return Math.getExponent(num);
}
/**
* Returns the unbiased exponent used in the representation of a double. This delegates to
* {@link Math#getExponent(double)} on most platforms, but on GWT it uses a super-sourced implementation.
* @param num any double
* @return the unbiased exponent of num, from {@link Double#MIN_EXPONENT} - 1 to {@link Double#MAX_EXPONENT} + 1
*/
public static int getExponent(double num) {
return Math.getExponent(num);
}
/**
* Returns the number of contiguous '0' bits in {@code n} starting at the sign bit and checking towards the
* least-significant bit, stopping just before a '1' bit is encountered. Returns 0 for any negative input.
* Returns 32 for an input of 0.
*
* This simply calls {@link Integer#numberOfLeadingZeros(int)} on most platforms, but on GWT, it calls the
* JS built-in function {@code Math.clz32(n)}. This probably performs better than the Integer method on GWT.
* @param n any int
* @return the number of '0' bits starting at the sign bit and going until just before a '1' bit is encountered
*/
public static int countLeadingZeros(int n) {
return Integer.numberOfLeadingZeros(n);
}
/**
* Returns the number of contiguous '0' bits in {@code n} starting at the least-significant bit and checking towards
* the sign bit, stopping just before a '1' bit is encountered. Returns 0 for any odd-number input.
* Returns 32 for an input of 0.
*
* This simply calls {@link Integer#numberOfTrailingZeros(int)} on most platforms, but on GWT, it uses the
* JS built-in function {@code Math.clz32(n)} with some extra steps to get the trailing, rather than leading,
* zeros. This probably performs better than the Integer method on GWT, though not as well as
* {@link #countLeadingZeros(int)}
* @param n any int
* @return the number of '0' bits starting at the least-significant bit and going until just before a '1' bit is encountered
*/
public static int countTrailingZeros(int n) {
return Integer.numberOfTrailingZeros(n);
}
/**
* Returns the number of contiguous '0' bits in {@code n} starting at the sign bit and checking towards the
* least-significant bit, stopping just before a '1' bit is encountered. Returns 0 for any negative input.
* Returns 64 for an input of 0.
*
* This simply calls {@link Long#numberOfLeadingZeros(long)} on most platforms, but on GWT, it calls
* {@link #countLeadingZeros(int)}, which calls the JS built-in function {@code Math.clz32(n)}.
* This probably performs better than the Long method on GWT.
* @param n any long
* @return the number of '0' bits starting at the sign bit and going until just before a '1' bit is encountered
*/
public static int countLeadingZeros(long n) {
return Long.numberOfLeadingZeros(n);
}
/**
* Returns the number of contiguous '0' bits in {@code n} starting at the least-significant bit and checking towards
* the sign bit, stopping just before a '1' bit is encountered. Returns 0 for any odd-number input.
* Returns 64 for an input of 0.
*
* This simply calls {@link Long#numberOfTrailingZeros(long)} on most platforms, but on GWT, it calls
* {@link #countTrailingZeros(int)}, which uses the JS built-in function {@code Math.clz32(n)}. This probably
* performs better than the Long method on GWT, though not as well as {@link #countLeadingZeros(long)}.
* @param n any int
* @return the number of '0' bits starting at the least-significant bit and going until just before a '1' bit is encountered
*/
public static int countTrailingZeros(long n) {
return Long.numberOfTrailingZeros(n);
}
}