Files
icegps-geotools/math/src/main/java/com/icegps/memory/DoubleBits.kt
2025-11-26 18:58:15 +08:00

48 lines
2.7 KiB
Kotlin

package com.icegps.memory
// S | EEEEEEEEEEE | FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
// S=1
// E=11
// F=52
fun Double.toStringInfo() = buildString(128) {
append(this@toStringInfo)
append(" = Double.fromParts(")
append("sign=")
append(this@toStringInfo.bitsSign)
append(", exponent=0b")
append(this@toStringInfo.bitsExponent.toString(2).padStart(11, '0'))
append(", mantissa=0b")
//append(this@toStringInfo.bitsMantissaLong.toString(2).padStart(52, '0'))
append(this@toStringInfo.bitsMantissaHigh.toString(2).padStart(20, '0'))
append(this@toStringInfo.bitsMantissaLow.toString(2).padStart(32, '0'))
append(")")
}
private const val TWO_POW_32_DOUBLE = 4294967296.0
val Double.Companion.TWO_POW_32 get() = TWO_POW_32_DOUBLE
fun Double.Companion.fromParts(sign: Int, exponent: Int, mantissa: Double): Double = fromParts(sign, exponent, (mantissa % TWO_POW_32_DOUBLE).toInt(), (mantissa / TWO_POW_32_DOUBLE).toInt())
fun Double.Companion.fromParts(sign: Int, exponent: Int, mantissa: Long): Double = fromParts(sign, exponent, mantissa.low, mantissa.high)
fun Double.Companion.fromParts(sign: Int, exponent: Int, mantissaLow: Int, mantissaHigh: Int): Double = fromLowHigh(mantissaLow, mantissaHigh.insert12(exponent, 20).insert1(sign, 31))
fun Double.Companion.fromLowHigh(low: Int, high: Int): Double = fromLowHighBitsSlow(low, high)
inline fun <T> Double.getLowHighBits(block: (low: Int, high: Int) -> T): T = getLowHighBitsSlow<T>(block)
/** Bit-wise equals without considering NaNs */
fun Double.equalsRaw(other: Double): Boolean = equalsRawSlow(other)
val Double.lowBits: Int get() = lowSlow
val Double.highBits: Int get() = highSlow
val Double.bitsSign: Int get() = highBits.extract1(31)
val Double.bitsExponent: Int get() = highBits.extract11(20)
val Double.bitsMantissaHigh: Int get() = highBits.extract20(0)
val Double.bitsMantissaLow: Int get() = lowBits
val Double.bitsMantissaDouble: Double get() = bitsMantissaLow.toDouble() + bitsMantissaHigh.toDouble() * TWO_POW_32_DOUBLE
val Double.bitsMantissaLong: Long get() = Long.fromLowHigh(bitsMantissaLow, bitsMantissaHigh)
@PublishedApi internal fun Double.Companion.fromLowHighBitsSlow(low: Int, high: Int): Double = Double.fromBits(Long.fromLowHigh(low, high))
@PublishedApi internal inline fun <T> Double.getLowHighBitsSlow(block: (low: Int, high: Int) -> T): T = block(lowSlow, highSlow)
@PublishedApi internal inline fun Double.equalsRawSlow(other: Double): Boolean = this.reinterpretAsLong().equals(other.reinterpretAsLong())
@PublishedApi internal val Double.lowSlow: Int get() = this.reinterpretAsLong().low
@PublishedApi internal val Double.highSlow: Int get() = this.reinterpretAsLong().high