/* dCache - http://www.dcache.org/
*
* Copyright (C) 2016 Deutsches Elektronen-Synchrotron
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.dcache.util;
import com.google.common.math.LongMath;
import com.google.common.primitives.Ints;
import static org.dcache.util.ByteUnit.Type.BINARY;
import static org.dcache.util.ByteUnit.Type.DECIMAL;
/**
* A ByteUnit represents a scaling factor applied to some number of bytes.
* Such scaling factors are intended to make it easier for humans to understand
* large (and small) numbers and understand how two numbers compare; as such,
* ByteUnit is often used with interfacing with humans.
* <p>
* There are two types of ByteUnit: ones that use decimal (base-10) prefixes and
* ones that use binary (base-2) prefixes. Decimal prefixes represent scaling
* factors of the form 10^3n, where n is some non-negative integer. Binary
* prefixes represent scaling factors of the form 2^10n, where n is some
* non-negative integer. ByteUnit.BYTES is considered both a decimal and
* binary scaling factor (i.e., with n=0 in both cases).
* <p>
* To avoid potential ambiguity, the ByteUnit enum values use ISO symbols. It
* contains both binary and decimal prefixes in strict ascending order.
* <p>
* Conversions are supported for int, long, float and double. For the two
* integer types (int and long) the maximum value is taken as a special case:
* any conversion is always the same MAX_VALUE. For integer numbers less than
* the maximum value, the conversion could overflow (be less than MIN_VALUE or
* more than MAX_VALUE). If a conversion would overflow then an
* ArithmeticException is thrown.
* <p>
* The maximum int and long values (Integer.MAX_VALUE and Long.MAX_VALUE
* respectively) are accepted as a special case: any conversion will return the
* same value.
*/
public enum ByteUnit
{
/**
* Represents no scaling has been applied.
*/
BYTES {
@Override
public boolean hasType(Type type)
{
return true;
}
@Override
public long toBytes(long d)
{
return d;
}
@Override
public double toBytes(double d)
{
return d;
}
@Override
public long toKB(long d)
{
return divideKeepingSaturation(d, 1_000L);
}
@Override
public double toKB(double d)
{
return d / 1_000d;
}
@Override
public long toKiB(long d)
{
return divideKeepingSaturation(d, 1L << 10);
}
@Override
public double toKiB(double d)
{
return d / (1L << 10);
}
@Override
public long toMB(long d)
{
return divideKeepingSaturation(d, 1_000_000L);
}
@Override
public double toMB(double d)
{
return d / 1_000_000;
}
@Override
public long toMiB(long d)
{
return divideKeepingSaturation(d, 1L << 20);
}
@Override
public double toMiB(double d)
{
return d / (1L << 20);
}
@Override
public long toGB(long d)
{
return divideKeepingSaturation(d, 1_000_000_000L);
}
@Override
public double toGB(double d)
{
return d / 1_000_000_000L;
}
@Override
public long toGiB(long d)
{
return divideKeepingSaturation(d, 1L << 30);
}
@Override
public double toGiB(double d)
{
return d / (1L << 30);
}
@Override
public long toTB(long d)
{
return divideKeepingSaturation(d, 1_000_000_000_000L);
}
@Override
public double toTB(double d)
{
return d / 1_000_000_000_000L;
}
@Override
public long toTiB(long d)
{
return divideKeepingSaturation(d, 1L << 40);
}
@Override
public double toTiB(double d)
{
return d / (1L << 40);
}
@Override
public long toPB(long d)
{
return divideKeepingSaturation(d, 1_000_000_000_000_000L);
}
@Override
public double toPB(double d)
{
return d / 1_000_000_000_000_000L;
}
@Override
public long toPiB(long d)
{
return divideKeepingSaturation(d, 1L << 50);
}
@Override
public double toPiB(double d)
{
return d / (1L << 50);
}
@Override
public long convert(long value, ByteUnit units)
{
return units.toBytes(value);
}
@Override
public double convert(double value, ByteUnit units)
{
return units.toBytes(value);
}
},
KB {
@Override
public boolean hasType(Type type)
{
return type == DECIMAL;
}
@Override
public long toBytes(long d)
{
return multiplyKeepingSaturation(d, 1_000L);
}
@Override
public double toBytes(double d)
{
return d * 1_000d;
}
@Override
public long toKB(long d)
{
return d;
}
@Override
public double toKB(double d)
{
return d;
}
@Override
public long toMB(long d)
{
return divideKeepingSaturation(d, 1_000L);
}
@Override
public long toGB(long d)
{
return divideKeepingSaturation(d, 1_000_000L);
}
@Override
public long toTB(long d)
{
return divideKeepingSaturation(d, 1_000_000_000L);
}
@Override
public long toPB(long d)
{
return divideKeepingSaturation(d, 1_000_000_000_000L);
}
@Override
public long convert(long value, ByteUnit units)
{
return units.toKB(value);
}
@Override
public double convert(double value, ByteUnit units)
{
return units.toKB(value);
}
},
KiB {
@Override
public boolean hasType(Type type)
{
return type == BINARY;
}
@Override
public long toBytes(long d)
{
return multiplyKeepingSaturation(d, 1L << 10);
}
@Override
public double toBytes(double d)
{
return d * (1L << 10);
}
@Override
public long toKiB(long d)
{
return d;
}
@Override
public double toKiB(double d)
{
return d;
}
@Override
public long toMiB(long d)
{
return divideKeepingSaturation(d, 1L << 10);
}
@Override
public long toGiB(long d)
{
return divideKeepingSaturation(d, 1L << 20);
}
@Override
public long toTiB(long d)
{
return divideKeepingSaturation(d, 1L << 30);
}
@Override
public long toPiB(long d)
{
return divideKeepingSaturation(d, 1L << 40);
}
@Override
public long convert(long value, ByteUnit units)
{
return units.toKiB(value);
}
@Override
public double convert(double value, ByteUnit units)
{
return units.toKiB(value);
}
},
MB {
@Override
public boolean hasType(Type type)
{
return type == DECIMAL;
}
@Override
public long toBytes(long d)
{
return multiplyKeepingSaturation(d, 1_000_000L);
}
@Override
public double toBytes(double d)
{
return d * 1_000_000d;
}
@Override
public long toKB(long d)
{
return multiplyKeepingSaturation(d, 1_000L);
}
@Override
public long toMB(long d)
{
return d;
}
@Override
public double toMB(double d)
{
return d;
}
@Override
public long toGB(long d)
{
return divideKeepingSaturation(d, 1_000L);
}
@Override
public long toTB(long d)
{
return divideKeepingSaturation(d, 1_000_000L);
}
@Override
public long toPB(long d)
{
return divideKeepingSaturation(d, 1_000_000_000L);
}
@Override
public long convert(long value, ByteUnit units)
{
return units.toMB(value);
}
@Override
public double convert(double value, ByteUnit units)
{
return units.toMB(value);
}
},
MiB {
@Override
public boolean hasType(Type type)
{
return type == BINARY;
}
@Override
public long toBytes(long d)
{
return multiplyKeepingSaturation(d, 1L << 20);
}
@Override
public double toBytes(double d)
{
return d * (1L << 20);
}
@Override
public long toKiB(long d)
{
return multiplyKeepingSaturation(d, 1L << 10);
}
@Override
public long toMiB(long d)
{
return d;
}
@Override
public double toMiB(double d)
{
return d;
}
@Override
public long toGiB(long d)
{
return divideKeepingSaturation(d, 1L << 10);
}
@Override
public long toTiB(long d)
{
return divideKeepingSaturation(d, 1L << 20);
}
@Override
public long toPiB(long d)
{
return divideKeepingSaturation(d, 1L << 30);
}
@Override
public long convert(long value, ByteUnit units)
{
return units.toMiB(value);
}
@Override
public double convert(double value, ByteUnit units)
{
return units.toMiB(value);
}
},
GB {
@Override
public boolean hasType(Type type)
{
return type == DECIMAL;
}
@Override
public long toBytes(long d)
{
return multiplyKeepingSaturation(d, 1_000_000_000L);
}
@Override
public double toBytes(double d)
{
return d * 1_000_000_000L;
}
@Override
public long toKB(long d)
{
return multiplyKeepingSaturation(d, 1_000_000L);
}
@Override
public long toMB(long d)
{
return multiplyKeepingSaturation(d, 1_000L);
}
@Override
public long toGB(long d)
{
return d;
}
@Override
public double toGB(double d)
{
return d;
}
@Override
public long toTB(long d)
{
return divideKeepingSaturation(d, 1_000L);
}
@Override
public long toPB(long d)
{
return divideKeepingSaturation(d, 1_000_000L);
}
@Override
public long convert(long value, ByteUnit units)
{
return units.toGB(value);
}
@Override
public double convert(double value, ByteUnit units)
{
return units.toGB(value);
}
},
GiB {
@Override
public boolean hasType(Type type)
{
return type == BINARY;
}
@Override
public long toBytes(long d)
{
return multiplyKeepingSaturation(d, 1L << 30);
}
@Override
public double toBytes(double d)
{
return d * (1L << 30);
}
@Override
public long toKiB(long d)
{
return multiplyKeepingSaturation(d, 1L << 20);
}
@Override
public long toMiB(long d)
{
return multiplyKeepingSaturation(d, 1L << 10);
}
@Override
public long toGiB(long d)
{
return d;
}
@Override
public double toGiB(double d)
{
return d;
}
@Override
public long toTiB(long d)
{
return divideKeepingSaturation(d, 1L << 10);
}
@Override
public long toPiB(long d)
{
return divideKeepingSaturation(d, 1L << 20);
}
@Override
public long convert(long value, ByteUnit units)
{
return units.toGiB(value);
}
@Override
public double convert(double value, ByteUnit units)
{
return units.toGiB(value);
}
},
TB {
@Override
public boolean hasType(Type type)
{
return type == DECIMAL;
}
@Override
public long toBytes(long d)
{
return multiplyKeepingSaturation(d, 1_000_000_000_000L);
}
@Override
public double toBytes(double d)
{
return d * 1_000_000_000_000d;
}
@Override
public long toKB(long d)
{
return multiplyKeepingSaturation(d, 1_000_000_000L);
}
@Override
public long toMB(long d)
{
return multiplyKeepingSaturation(d, 1_000_000L);
}
@Override
public long toGB(long d)
{
return multiplyKeepingSaturation(d, 1_000L);
}
@Override
public long toTB(long d)
{
return d;
}
@Override
public double toTB(double d)
{
return d;
}
@Override
public long toPB(long d)
{
return divideKeepingSaturation(d, 1_000L);
}
@Override
public long convert(long value, ByteUnit units)
{
return units.toTB(value);
}
@Override
public double convert(double value, ByteUnit units)
{
return units.toTB(value);
}
},
TiB {
@Override
public boolean hasType(Type type)
{
return type == BINARY;
}
@Override
public long toBytes(long d)
{
return multiplyKeepingSaturation(d, 1L << 40);
}
@Override
public double toBytes(double d)
{
return d * (1L << 40);
}
@Override
public long toKiB(long d)
{
return multiplyKeepingSaturation(d, 1L << 30);
}
@Override
public long toMiB(long d)
{
return multiplyKeepingSaturation(d, 1L << 20);
}
@Override
public long toGiB(long d)
{
return multiplyKeepingSaturation(d, 1L << 10);
}
@Override
public long toTiB(long d)
{
return d;
}
@Override
public double toTiB(double d)
{
return d;
}
@Override
public long toPiB(long d)
{
return divideKeepingSaturation(d, 1L << 10);
}
@Override
public long convert(long value, ByteUnit units)
{
return units.toTiB(value);
}
@Override
public double convert(double value, ByteUnit units)
{
return units.toTiB(value);
}
},
PB {
@Override
public boolean hasType(Type type)
{
return type == DECIMAL;
}
@Override
public long toBytes(long d)
{
return multiplyKeepingSaturation(d, 1_000_000_000_000_000L);
}
@Override
public double toBytes(double d)
{
return d * 1_000_000_000_000_000d;
}
@Override
public long toKB(long d)
{
return multiplyKeepingSaturation(d, 1_000_000_000_000L);
}
@Override
public long toMB(long d)
{
return multiplyKeepingSaturation(d, 1_000_000_000L);
}
@Override
public long toGB(long d)
{
return multiplyKeepingSaturation(d, 1_000_000L);
}
@Override
public long toTB(long d)
{
return multiplyKeepingSaturation(d, 1_000L);
}
@Override
public long toPB(long d)
{
return d;
}
@Override
public double toPB(double d)
{
return d;
}
@Override
public long convert(long value, ByteUnit units)
{
return units.toPB(value);
}
@Override
public double convert(double value, ByteUnit units)
{
return units.toPB(value);
}
},
PiB {
@Override
public boolean hasType(Type type)
{
return type == BINARY;
}
@Override
public long toBytes(long d)
{
return multiplyKeepingSaturation(d, 1L << 50);
}
@Override
public double toBytes(double d)
{
return d * (1L << 50);
}
@Override
public long toKiB(long d)
{
return multiplyKeepingSaturation(d, 1L << 40);
}
@Override
public long toMiB(long d)
{
return multiplyKeepingSaturation(d, 1L << 30);
}
@Override
public long toGiB(long d)
{
return multiplyKeepingSaturation(d, 1L << 20);
}
@Override
public long toTiB(long d)
{
return multiplyKeepingSaturation(d, 1L << 10);
}
@Override
public long toPiB(long d)
{
return d;
}
@Override
public double toPiB(double d)
{
return d;
}
@Override
public long convert(long value, ByteUnit units)
{
return units.toPiB(value);
}
@Override
public double convert(double value, ByteUnit units)
{
return units.toPiB(value);
}
};
/**
* In which numerical base a BaseUnit is founded: base-10 or base-2.
* Most BaseUnit values are either base-10 or base-2 with the exception of
* BYTES which is considered both.
*/
public enum Type
{
/**
* A ByteUnit that is base-10. Stated values must be multiplied by
* 10^3n for some non-negative integer n: BYTES for n=0, KILOBYTES for
* n=1 and so on.
*/
DECIMAL {
@Override
public ByteUnit unitsOf(long value, long minValue)
{
long absValue = value == Long.MIN_VALUE ? Long.MAX_VALUE : Math.abs(value);
if (absValue < KB.toBytes(minValue)) {
return BYTES;
}
if (absValue < MB.toBytes(minValue)) {
return KB;
}
if (absValue < GB.toBytes(minValue)) {
return MB;
}
if (absValue < TB.toBytes(minValue)) {
return GB;
}
if (absValue < PB.toBytes(minValue)) {
return TB;
}
return PB;
}
@Override
public ByteUnit unitsOf(double value, double minValue)
{
double absValue = Math.abs(value);
if (absValue < KB.toBytes(minValue)) {
return BYTES;
}
if (absValue < MB.toBytes(minValue)) {
return KB;
}
if (absValue < GB.toBytes(minValue)) {
return MB;
}
if (absValue < TB.toBytes(minValue)) {
return GB;
}
if (absValue < PB.toBytes(minValue)) {
return TB;
}
return PB;
}
@Override
public ByteUnit exactUnitsOf(long value)
{
long absValue = Math.abs(value);
if (absValue >= PB.toBytes(1L) && absValue % PB.toBytes(1L) == 0) {
return PB;
}
if (absValue >= TB.toBytes(1L) && absValue % TB.toBytes(1L) == 0) {
return TB;
}
if (absValue >= GB.toBytes(1L) && absValue % GB.toBytes(1L) == 0) {
return GB;
}
if (absValue >= MB.toBytes(1L) && absValue % MB.toBytes(1L) == 0) {
return MB;
}
if (absValue >= KB.toBytes(1L) && absValue % KB.toBytes(1L) == 0) {
return KB;
}
return BYTES;
}
},
/**
* A ByteUnit that is base-2. Stated values must be multiplied by
* 2^10n for some non-negative integer n: BYTES for n=0, KIBIBYTES for
* n=1 and so on.
*/
BINARY {
@Override
public ByteUnit unitsOf(long value, long minValue)
{
long absValue = value == Long.MIN_VALUE ? Long.MAX_VALUE : Math.abs(value);
if (absValue < KiB.toBytes(minValue)) {
return BYTES;
}
if (absValue < MiB.toBytes(minValue)) {
return KiB;
}
if (absValue < GiB.toBytes(minValue)) {
return MiB;
}
if (absValue < TiB.toBytes(minValue)) {
return GiB;
}
if (absValue < PiB.toBytes(minValue)) {
return TiB;
}
return PiB;
}
@Override
public ByteUnit unitsOf(double value, double minValue)
{
double absValue = Math.abs(value);
if (absValue < KiB.toBytes(minValue)) {
return BYTES;
}
if (absValue < MiB.toBytes(minValue)) {
return KiB;
}
if (absValue < GiB.toBytes(minValue)) {
return MiB;
}
if (absValue < TiB.toBytes(minValue)) {
return GiB;
}
if (absValue < PiB.toBytes(minValue)) {
return TiB;
}
return PiB;
}
@Override
public ByteUnit exactUnitsOf(long value)
{
long absValue = Math.abs(value);
if (absValue >= PiB.toBytes(1L) && absValue % PiB.toBytes(1L) == 0) {
return PiB;
}
if (absValue >= TiB.toBytes(1L) && absValue % TiB.toBytes(1L) == 0) {
return TiB;
}
if (absValue >= GiB.toBytes(1L) && absValue % GiB.toBytes(1L) == 0) {
return GiB;
}
if (absValue >= MiB.toBytes(1L) && absValue % MiB.toBytes(1L) == 0) {
return MiB;
}
if (absValue >= KiB.toBytes(1L) && absValue % KiB.toBytes(1L) == 0) {
return KiB;
}
return BYTES;
}
};
/**
* Returns which units to use when describing this value. More
* specifically, it returns the ByteUnit prefix that, when
* {@code convert(value, ByteUnit.BYTES);} is called, returns the
* smallest absolute non-zero value.
* If {@literal value} is zero then ByteUnit.BYTES is returned.
*/
public ByteUnit unitsOf(long value)
{
return unitsOf(value, 1L);
}
/**
* Return which units to use when describing this value. More
* specifically, it returns the largest ByteUnit that, when calling
* {@code convert(value, ByteUnit.BYTES);}, returns a value of at least
* {@literal minValue}.
* If {@literal value} is zero then ByteUnit.BYTES is returned.
*/
public abstract ByteUnit unitsOf(long value, long minValue);
/**
* Returns which units to use when describing this value. More
* specifically, it returns the ByteUnit prefix that, when
* {@code convert(value, ByteUnit.BYTES);} is called, returns at least
* 1. If {@literal value} is zero then ByteUnit.BYTES is returned.
*/
public ByteUnit unitsOf(double value)
{
return unitsOf(value, 1d);
}
/**
* Return which units to use when describing this value. More
* specifically, it returns the largest ByteUnit that, when calling
* {@code convert(value, ByteUnit.BYTES);}, returns a value of at least
* {@literal minValue}. If {@literal value} is zero then
* ByteUnit.BYTES is returned.
*/
public abstract ByteUnit unitsOf(double value, double minValue);
/**
* Provide the largest ByteUnit where the supplied value can be
* represented exactly. If zero is supplied then ByteUnit.BYTES is
* returned.
*/
public abstract ByteUnit exactUnitsOf(long value);
}
/**
* Return whether this Prefix has the supplied type. Note that
* this method always returns true for ByteUnit.BYTES
*/
public abstract boolean hasType(Type type);
/**
* Return Long.MAX_VALUE if either argument is Long.MAX_VALUE, otherwise
* return the result of multiplying the two arguments or throw an exception
* if the result overflows.
*/
private static long multiplyKeepingSaturation(long a, long b) throws ArithmeticException
{
if (a == Long.MAX_VALUE || b == Long.MAX_VALUE) {
return Long.MAX_VALUE;
}
return LongMath.checkedMultiply(a, b);
}
/** Return Long.MAX_VALUE if first value is same, otherwise do integer division. */
private static long divideKeepingSaturation(long dividend, long divisor)
{
if (dividend == Long.MAX_VALUE) {
return Long.MAX_VALUE;
}
return dividend / divisor;
}
/** A version of Guava's Ints.checkedCast that throws ArithmeticException. */
private static int checkedCast(long value) throws ArithmeticException
{
try {
return Ints.checkedCast(value);
} catch (IllegalArgumentException inner) {
ArithmeticException e = new ArithmeticException(inner.getMessage());
e.addSuppressed(inner);
throw e;
}
}
/**
* Converts the given value in the given prefix to this prefix.
* Conversions from smaller to larger prefix truncate, so lose
* precision. For example, converting 999 KILO to MEGA results in 0.
* Conversions from larger to smaller granularities with arguments that
* would numerically overflow saturate to Long.MIN_VALUE if negative or
* Long.MAX_VALUE if positive.
* For example, to convert 10 PEBI to MEBI, use: Prefix.MEBI.convert(10L, Prefix.PEBI)
* @param sourceValue the value in some other prefix
* @param sourcePrefix the prefix of sourceValue
* @return the value in this prefix.
*/
public abstract long convert(long sourceValue, ByteUnit sourcePrefix);
public abstract double convert(double sourceValue, ByteUnit sourcePrefix);
public int convert(int sourceValue, ByteUnit sourcePrefix)
{
if (sourceValue == Integer.MAX_VALUE) {
return sourceValue;
}
return checkedCast(convert((long) sourceValue, sourcePrefix));
}
public int toBytes(int d)
{
if (d == Integer.MAX_VALUE) {
return d;
}
return checkedCast(toBytes((long)d));
}
public abstract long toBytes(long d);
public float toBytes(float d)
{
return (float) toBytes((double)d);
}
public abstract double toBytes(double d);
public int toKB(int d)
{
if (d == Integer.MAX_VALUE) {
return d;
}
return checkedCast(toKB((long)d));
}
public long toKB(long d)
{
return BYTES.toKB(toBytes(d));
}
public float toKB(float d)
{
return (float) toKB((double) d);
}
public double toKB(double d)
{
return BYTES.toKB(toBytes(d));
}
public int toKiB(int d)
{
if (d == Integer.MAX_VALUE) {
return d;
}
return checkedCast(toKiB((long) d));
}
public long toKiB(long d)
{
return BYTES.toKiB(toBytes(d));
}
public float toKiB(float d)
{
return (float) toKiB((double) d);
}
public double toKiB(double d)
{
return BYTES.toKiB(toBytes(d));
}
public int toMB(int d)
{
if (d == Integer.MAX_VALUE) {
return d;
}
return checkedCast(toMB((long) d));
}
public long toMB(long d)
{
return BYTES.toMB(toBytes(d));
}
public float toMB(float d)
{
return (float) toMB((double) d);
}
public double toMB(double d)
{
return BYTES.toMB(toBytes(d));
}
public int toMiB(int d)
{
if (d == Integer.MAX_VALUE) {
return d;
}
return checkedCast(toMiB((long) d));
}
public long toMiB(long d)
{
return BYTES.toMiB(toBytes(d));
}
public float toMiB(float d)
{
return (float) toMiB((double) d);
}
public double toMiB(double d)
{
return BYTES.toMiB(toBytes(d));
}
public long toGB(long d)
{
return BYTES.toGB(toBytes(d));
}
public int toGB(int d)
{
if (d == Integer.MAX_VALUE) {
return d;
}
return checkedCast(toGB((long) d));
}
public float toGB(float d)
{
return (float) toGB((double) d);
}
public double toGB(double d)
{
return BYTES.toGB(toBytes(d));
}
public long toGiB(long d)
{
return BYTES.toGiB(toBytes(d));
}
public int toGiB(int d)
{
if (d == Integer.MAX_VALUE) {
return d;
}
return checkedCast(toGiB((long) d));
}
public float toGiB(float d)
{
return (float) toGiB((double) d);
}
public double toGiB(double d)
{
return BYTES.toGiB(toBytes(d));
}
public long toTB(long d)
{
return BYTES.toTB(toBytes(d));
}
public int toTB(int d)
{
if (d == Integer.MAX_VALUE) {
return d;
}
return checkedCast(toTB((long)d));
}
public float toTB(float d)
{
return (float) toTB((double) d);
}
public double toTB(double d)
{
return BYTES.toTB(toBytes(d));
}
public long toTiB(long d)
{
return BYTES.toTiB(toBytes(d));
}
public int toTiB(int d)
{
if (d == Integer.MAX_VALUE) {
return d;
}
return checkedCast(toTiB((long) d));
}
public float toTiB(float d)
{
return (float) toTiB((double) d);
}
public double toTiB(double d)
{
return BYTES.toTiB(toBytes(d));
}
public long toPB(long d)
{
return BYTES.toPB(toBytes(d));
}
public int toPB(int d)
{
if (d == Integer.MAX_VALUE) {
return d;
}
return checkedCast(toPB((long) d));
}
public float toPB(float d)
{
return (float) toPB((double) d);
}
public double toPB(double d)
{
return BYTES.toPB(toBytes(d));
}
public long toPiB(long d)
{
return BYTES.toPiB(toBytes(d));
}
public int toPiB(int d)
{
if (d == Integer.MAX_VALUE) {
return d;
}
return checkedCast(toPiB((long) d));
}
public float toPiB(float d)
{
return (float) toPiB((double) d);
}
public double toPiB(double d)
{
return BYTES.toPiB(toBytes(d));
}
}