ImpreciseFraction
This commit is contained in:
parent
6cd04682d7
commit
dab5cd6a2b
@ -1,6 +1,5 @@
|
|||||||
package ru.dbotthepony.mc.otm.block.entity
|
package ru.dbotthepony.mc.otm.block.entity
|
||||||
|
|
||||||
import net.minecraft.MethodsReturnNonnullByDefault
|
|
||||||
import net.minecraft.core.BlockPos
|
import net.minecraft.core.BlockPos
|
||||||
import net.minecraft.network.chat.Component
|
import net.minecraft.network.chat.Component
|
||||||
import net.minecraft.network.chat.TranslatableComponent
|
import net.minecraft.network.chat.TranslatableComponent
|
||||||
@ -16,7 +15,6 @@ import ru.dbotthepony.mc.otm.capability.MatteryCapability
|
|||||||
import ru.dbotthepony.mc.otm.capability.MatteryMachineEnergyStorage
|
import ru.dbotthepony.mc.otm.capability.MatteryMachineEnergyStorage
|
||||||
import ru.dbotthepony.mc.otm.core.Fraction
|
import ru.dbotthepony.mc.otm.core.Fraction
|
||||||
import ru.dbotthepony.mc.otm.menu.AndroidStationMenu
|
import ru.dbotthepony.mc.otm.menu.AndroidStationMenu
|
||||||
import javax.annotation.ParametersAreNonnullByDefault
|
|
||||||
|
|
||||||
class BlockEntityAndroidStation(p_155229_: BlockPos, p_155230_: BlockState) :
|
class BlockEntityAndroidStation(p_155229_: BlockPos, p_155230_: BlockState) :
|
||||||
BlockEntityMatteryPowered(Registry.BlockEntities.ANDROID_STATION, p_155229_, p_155230_), MenuProvider {
|
BlockEntityMatteryPowered(Registry.BlockEntities.ANDROID_STATION, p_155229_, p_155230_), MenuProvider {
|
||||||
|
@ -1,16 +1,12 @@
|
|||||||
package ru.dbotthepony.mc.otm.block.entity.worker
|
package ru.dbotthepony.mc.otm.block.entity.worker
|
||||||
|
|
||||||
import net.minecraft.MethodsReturnNonnullByDefault
|
|
||||||
import javax.annotation.ParametersAreNonnullByDefault
|
|
||||||
import net.minecraft.world.level.block.entity.BlockEntityType
|
import net.minecraft.world.level.block.entity.BlockEntityType
|
||||||
import net.minecraft.core.BlockPos
|
import net.minecraft.core.BlockPos
|
||||||
import net.minecraft.world.level.block.state.BlockState
|
import net.minecraft.world.level.block.state.BlockState
|
||||||
import ru.dbotthepony.mc.otm.block.entity.BlockEntityMatteryPowered
|
import ru.dbotthepony.mc.otm.block.entity.BlockEntityMatteryPowered
|
||||||
import net.minecraft.nbt.CompoundTag
|
import net.minecraft.nbt.CompoundTag
|
||||||
import net.minecraft.nbt.DoubleTag
|
import net.minecraft.nbt.DoubleTag
|
||||||
import net.minecraft.world.level.Level
|
|
||||||
import net.minecraft.world.level.block.Block
|
import net.minecraft.world.level.block.Block
|
||||||
import net.minecraft.world.level.block.entity.BlockEntity
|
|
||||||
import ru.dbotthepony.mc.otm.core.Fraction
|
import ru.dbotthepony.mc.otm.core.Fraction
|
||||||
import ru.dbotthepony.mc.otm.ifHas
|
import ru.dbotthepony.mc.otm.ifHas
|
||||||
import ru.dbotthepony.mc.otm.set
|
import ru.dbotthepony.mc.otm.set
|
||||||
|
@ -11,7 +11,6 @@ import ru.dbotthepony.mc.otm.set
|
|||||||
import ru.dbotthepony.mc.otm.storage.IStorageTuple
|
import ru.dbotthepony.mc.otm.storage.IStorageTuple
|
||||||
import ru.dbotthepony.mc.otm.storage.ItemStackWrapper
|
import ru.dbotthepony.mc.otm.storage.ItemStackWrapper
|
||||||
import ru.dbotthepony.mc.otm.storage.StorageObjectRegistry
|
import ru.dbotthepony.mc.otm.storage.StorageObjectRegistry
|
||||||
import ru.dbotthepony.mc.otm.storage.StorageObjectTuple
|
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class ItemMatteryDrive : AbstractMatteryDrive<ItemStackWrapper>, IItemMatteryDrive {
|
class ItemMatteryDrive : AbstractMatteryDrive<ItemStackWrapper>, IItemMatteryDrive {
|
||||||
|
@ -10,7 +10,7 @@ import java.math.BigInteger
|
|||||||
import java.math.MathContext
|
import java.math.MathContext
|
||||||
import java.math.RoundingMode
|
import java.math.RoundingMode
|
||||||
|
|
||||||
fun powScale(int: Int): BigInteger {
|
private fun powScale(int: Int): BigInteger {
|
||||||
if (int <= 0)
|
if (int <= 0)
|
||||||
return BigInteger.ONE
|
return BigInteger.ONE
|
||||||
|
|
||||||
@ -22,7 +22,7 @@ fun powScale(int: Int): BigInteger {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
fun powUnscaled(unscaled: BigInteger, scale: Int): BigInteger {
|
private fun powUnscaled(unscaled: BigInteger, scale: Int): BigInteger {
|
||||||
if (scale >= 0)
|
if (scale >= 0)
|
||||||
return unscaled
|
return unscaled
|
||||||
|
|
||||||
@ -37,7 +37,7 @@ fun powUnscaled(unscaled: BigInteger, scale: Int): BigInteger {
|
|||||||
val DEFAULT_MATH_CONTEXT = MathContext(64, RoundingMode.HALF_UP)
|
val DEFAULT_MATH_CONTEXT = MathContext(64, RoundingMode.HALF_UP)
|
||||||
|
|
||||||
@Suppress("NOTHING_TO_INLINE")
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
inline fun invertCompare(int: Int): Int {
|
private inline fun invertCompare(int: Int): Int {
|
||||||
if (int == 0)
|
if (int == 0)
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
@ -206,7 +206,7 @@ private fun compactTwo(value1: BigInteger, value2: BigInteger, compact: Boolean
|
|||||||
return compactTwoMod(value1, value2, compact)
|
return compactTwoMod(value1, value2, compact)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun unsignedInt(value: Byte): Int {
|
private fun unsignedInt(value: Byte): Int {
|
||||||
if (value < 0) {
|
if (value < 0) {
|
||||||
return 256 + value
|
return 256 + value
|
||||||
}
|
}
|
||||||
|
322
src/main/kotlin/ru/dbotthepony/mc/otm/core/ImpreciseFraction.kt
Normal file
322
src/main/kotlin/ru/dbotthepony/mc/otm/core/ImpreciseFraction.kt
Normal file
@ -0,0 +1,322 @@
|
|||||||
|
package ru.dbotthepony.mc.otm.core
|
||||||
|
|
||||||
|
import net.minecraft.nbt.ByteArrayTag
|
||||||
|
import net.minecraft.nbt.StringTag
|
||||||
|
import net.minecraft.nbt.Tag
|
||||||
|
import java.math.BigDecimal
|
||||||
|
import java.math.BigInteger
|
||||||
|
import java.math.MathContext
|
||||||
|
import java.nio.ByteBuffer
|
||||||
|
import kotlin.math.absoluteValue
|
||||||
|
|
||||||
|
private fun isZero(value: BigInteger) = value == BigInteger.ZERO
|
||||||
|
|
||||||
|
private val LONG_BUFF = ByteBuffer.allocate(8)
|
||||||
|
|
||||||
|
private fun longToBytes(value: Long): ByteArray {
|
||||||
|
LONG_BUFF.position(0)
|
||||||
|
LONG_BUFF.putLong(value)
|
||||||
|
return LONG_BUFF.array().copyOf()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun bytesToLong(value: ByteArray, from: Int = 0): Long {
|
||||||
|
val arr = LONG_BUFF.array()
|
||||||
|
arr[0] = value[from]
|
||||||
|
arr[1] = value[from + 1]
|
||||||
|
arr[2] = value[from + 2]
|
||||||
|
arr[3] = value[from + 3]
|
||||||
|
arr[4] = value[from + 4]
|
||||||
|
arr[5] = value[from + 5]
|
||||||
|
arr[6] = value[from + 6]
|
||||||
|
arr[7] = value[from + 7]
|
||||||
|
LONG_BUFF.position(0)
|
||||||
|
return LONG_BUFF.long
|
||||||
|
}
|
||||||
|
|
||||||
|
const val EPSILON = 0.0000001
|
||||||
|
|
||||||
|
private fun cmpDouble(a: Double, b: Double): Boolean {
|
||||||
|
if (a == b)
|
||||||
|
return true
|
||||||
|
|
||||||
|
return (a - b).absoluteValue <= EPSILON
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
|
class ImpreciseFraction @JvmOverloads constructor(whole: BigInteger, decimal: Double = 0.0) : Comparable<ImpreciseFraction> {
|
||||||
|
@JvmOverloads constructor(whole: Byte, decimal: Double = 0.0) : this(BigInteger.valueOf(whole.toLong()), decimal)
|
||||||
|
@JvmOverloads constructor(whole: Short, decimal: Double = 0.0) : this(BigInteger.valueOf(whole.toLong()), decimal)
|
||||||
|
@JvmOverloads constructor(whole: Int, decimal: Double = 0.0) : this(BigInteger.valueOf(whole.toLong()), decimal)
|
||||||
|
@JvmOverloads constructor(whole: Long, decimal: Double = 0.0) : this(BigInteger.valueOf(whole), decimal)
|
||||||
|
constructor(value: BigDecimal) : this(value.toBigInteger(), value.remainder(BigDecimal.ONE).toDouble()) // TODO
|
||||||
|
constructor(value: Float) : this(BigDecimal(value.toString()))
|
||||||
|
constructor(value: Double) : this(BigDecimal(value.toString()))
|
||||||
|
constructor(value: String) : this(BigDecimal(value))
|
||||||
|
|
||||||
|
val decimal: Double
|
||||||
|
val whole: BigInteger
|
||||||
|
|
||||||
|
init {
|
||||||
|
var decimal = decimal
|
||||||
|
var whole = whole
|
||||||
|
|
||||||
|
if (decimal <= -1f || decimal >= 1f) {
|
||||||
|
val frac = decimal % 1f
|
||||||
|
whole += BigInteger.valueOf((decimal - frac).toLong())
|
||||||
|
decimal = frac
|
||||||
|
}
|
||||||
|
|
||||||
|
// дробная часть равна нулю
|
||||||
|
if (decimal == -0.0 || decimal == 0.0) {
|
||||||
|
if (!isZero(whole)) {
|
||||||
|
this.decimal = 0.0
|
||||||
|
this.whole = whole
|
||||||
|
} else { // сохраняет минус ноль
|
||||||
|
this.decimal = decimal
|
||||||
|
this.whole = whole
|
||||||
|
}
|
||||||
|
// целая часть и дробная часть имеют одинаковые знаки
|
||||||
|
} else if (decimal > 0.0 && whole.signum() >= 0 || decimal < 0.0 && whole.signum() <= 0) {
|
||||||
|
this.decimal = decimal
|
||||||
|
this.whole = whole
|
||||||
|
} else {
|
||||||
|
// целая часть и дробная часть имеют разные знаки
|
||||||
|
|
||||||
|
if (decimal > 0.0) {
|
||||||
|
this.decimal = decimal - 1f
|
||||||
|
this.whole = whole + BigInteger.ONE
|
||||||
|
//} else if (double < 0.0 && whole.signum() > 0) {
|
||||||
|
} else {
|
||||||
|
this.decimal = decimal + 1f
|
||||||
|
this.whole = whole - BigInteger.ONE
|
||||||
|
}
|
||||||
|
|
||||||
|
//throw InternalError("This should never happen, but it happened. Input was: $whole $double")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isNaN() = decimal.isNaN()
|
||||||
|
|
||||||
|
operator fun plus(other: ImpreciseFraction) = ImpreciseFraction(whole + other.whole, decimal + other.decimal)
|
||||||
|
operator fun minus(other: ImpreciseFraction) = ImpreciseFraction(whole - other.whole, decimal - other.decimal)
|
||||||
|
|
||||||
|
operator fun times(other: ImpreciseFraction): ImpreciseFraction {
|
||||||
|
val a = whole
|
||||||
|
val c = other.whole
|
||||||
|
|
||||||
|
val b = 1.0 / decimal
|
||||||
|
val d = 1.0 / other.decimal
|
||||||
|
|
||||||
|
val bL = b.toLong()
|
||||||
|
val dL = d.toLong()
|
||||||
|
|
||||||
|
val bc = c.divideAndRemainder(BigInteger.valueOf(bL))
|
||||||
|
val ad = a.divideAndRemainder(BigInteger.valueOf(dL))
|
||||||
|
|
||||||
|
return ImpreciseFraction(
|
||||||
|
a * c + bc[0] + ad[0],
|
||||||
|
decimal * other.decimal + bc[1].toDouble() / b + ad[1].toDouble() / d
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun div(other: ImpreciseFraction): ImpreciseFraction {
|
||||||
|
val a = toBigDecmial()
|
||||||
|
val b = other.toBigDecmial()
|
||||||
|
val div = a.divideAndRemainder(b, MathContext(a.precision() + b.precision()))
|
||||||
|
|
||||||
|
val bD = b.toDouble()
|
||||||
|
|
||||||
|
if (bD.isInfinite()) {
|
||||||
|
return ImpreciseFraction(div[0].toBigInteger())
|
||||||
|
}
|
||||||
|
|
||||||
|
return ImpreciseFraction(div[0].toBigInteger(), div[1].toDouble() / bD)
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun unaryMinus(): ImpreciseFraction {
|
||||||
|
return ImpreciseFraction(-whole, decimal)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (isNaN())
|
||||||
|
return false
|
||||||
|
|
||||||
|
if (other is ImpreciseFraction) {
|
||||||
|
return other.whole == whole && cmpDouble(decimal, other.decimal)
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.equals(other)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun equalsStrict(other: Any?): Boolean {
|
||||||
|
if (isNaN())
|
||||||
|
return false
|
||||||
|
|
||||||
|
if (other is ImpreciseFraction) {
|
||||||
|
return other.whole == whole && other.decimal == decimal
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.equals(other)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
if (isNaN())
|
||||||
|
return Double.NaN.hashCode()
|
||||||
|
|
||||||
|
return 31 * decimal.hashCode() + whole.hashCode()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toString(): String {
|
||||||
|
if (isNaN())
|
||||||
|
return "NaN"
|
||||||
|
|
||||||
|
return when (signum()) {
|
||||||
|
1 -> "$whole.${decimal.toString().substring(2)}"
|
||||||
|
0 -> "0.0"
|
||||||
|
-1 -> "$whole.${decimal.toString().substring(3)}"
|
||||||
|
else -> throw IllegalArgumentException("invalid signum")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun toDouble(): Double {
|
||||||
|
return java.lang.Double.parseDouble(toString())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun toBigDecmial(): BigDecimal {
|
||||||
|
return BigDecimal(whole) + BigDecimal(decimal)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun signum(): Int {
|
||||||
|
val sign = whole.signum()
|
||||||
|
|
||||||
|
if (sign != 0) {
|
||||||
|
return sign
|
||||||
|
}
|
||||||
|
|
||||||
|
return if (decimal > 0.0) 1 else if (decimal < 0.0) -1 else 0
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun compareTo(other: ImpreciseFraction): Int {
|
||||||
|
if (isNaN())
|
||||||
|
return 1
|
||||||
|
else if (other.isNaN())
|
||||||
|
return -1
|
||||||
|
|
||||||
|
val a = signum()
|
||||||
|
val b = other.signum()
|
||||||
|
|
||||||
|
if (a < b)
|
||||||
|
return -1
|
||||||
|
else if (a > b)
|
||||||
|
return 1
|
||||||
|
|
||||||
|
if (other.whole == whole) {
|
||||||
|
if (cmpDouble(decimal, other.decimal)) {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
return if (other.decimal < decimal) 1 else -1
|
||||||
|
}
|
||||||
|
|
||||||
|
return whole.compareTo(other.whole)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun compareToStrict(other: ImpreciseFraction): Int {
|
||||||
|
if (isNaN())
|
||||||
|
return 1
|
||||||
|
else if (other.isNaN())
|
||||||
|
return -1
|
||||||
|
|
||||||
|
val a = signum()
|
||||||
|
val b = other.signum()
|
||||||
|
|
||||||
|
if (a < b)
|
||||||
|
return -1
|
||||||
|
else if (a > b)
|
||||||
|
return 1
|
||||||
|
|
||||||
|
if (other.whole == whole) {
|
||||||
|
if (other.decimal == decimal) {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
return if (other.decimal < decimal) 1 else -1
|
||||||
|
}
|
||||||
|
|
||||||
|
return whole.compareTo(other.whole)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun toBytesArray(): ByteArray {
|
||||||
|
val whole = whole.toByteArray()
|
||||||
|
return byteArrayOf(whole.size.toByte(), *whole, *longToBytes(decimal.toBits()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun serializeNBT(): Tag {
|
||||||
|
return ByteArrayTag(toBytesArray())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isZero() = cmpDouble(decimal, 0.0) && isZero(whole)
|
||||||
|
|
||||||
|
fun moreThanZero(): ImpreciseFraction {
|
||||||
|
if (signum() >= 0)
|
||||||
|
return this
|
||||||
|
|
||||||
|
return ZERO
|
||||||
|
}
|
||||||
|
|
||||||
|
fun lessOrZero(): ImpreciseFraction {
|
||||||
|
if (signum() <= 0)
|
||||||
|
return this
|
||||||
|
|
||||||
|
return ZERO
|
||||||
|
}
|
||||||
|
|
||||||
|
fun max(vararg others: ImpreciseFraction): ImpreciseFraction {
|
||||||
|
var max = this
|
||||||
|
|
||||||
|
for (other in others) {
|
||||||
|
if (max < other) {
|
||||||
|
max = other
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return max
|
||||||
|
}
|
||||||
|
|
||||||
|
fun min(vararg others: ImpreciseFraction): ImpreciseFraction {
|
||||||
|
var min = this
|
||||||
|
|
||||||
|
for (other in others) {
|
||||||
|
if (min > other) {
|
||||||
|
min = other
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return min
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
@JvmField val MINUS_ZERO = ImpreciseFraction(0, -0.0)
|
||||||
|
@JvmField val ZERO = ImpreciseFraction(BigInteger.ZERO)
|
||||||
|
@JvmField val ONE = ImpreciseFraction(BigInteger.ONE)
|
||||||
|
@JvmField val TWO = ImpreciseFraction(BigInteger.TWO)
|
||||||
|
@JvmField val TEN = ImpreciseFraction(BigInteger.TEN)
|
||||||
|
|
||||||
|
fun fromBytesArray(input: ByteArray): ImpreciseFraction {
|
||||||
|
val size = if (input[0] < 0) input[0].toInt() + 256 else input[0].toInt()
|
||||||
|
val slice = input.copyOfRange(1, 1 + size)
|
||||||
|
val bits = bytesToLong(input, 1 + size)
|
||||||
|
return ImpreciseFraction(BigInteger(slice), Double.fromBits(bits))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun deserializeNBT(input: Tag?): ImpreciseFraction {
|
||||||
|
if (input is ByteArrayTag) {
|
||||||
|
return fromBytesArray(input.asByteArray)
|
||||||
|
} else if (input is StringTag) {
|
||||||
|
return ImpreciseFraction(input.asString)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ZERO
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -6,8 +6,6 @@ import ru.dbotthepony.mc.otm.capability.matter.IPatternStorage
|
|||||||
import ru.dbotthepony.mc.otm.core.Fraction
|
import ru.dbotthepony.mc.otm.core.Fraction
|
||||||
import ru.dbotthepony.mc.otm.menu.MatteryMenu
|
import ru.dbotthepony.mc.otm.menu.MatteryMenu
|
||||||
import ru.dbotthepony.mc.otm.menu.data.FractionDataContainer
|
import ru.dbotthepony.mc.otm.menu.data.FractionDataContainer
|
||||||
import ru.dbotthepony.mc.otm.menu.data.IntDataContainer
|
|
||||||
import ru.dbotthepony.mc.otm.menu.data.ShortDataContainer
|
|
||||||
|
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
class LevelGaugeWidget(menu: MatteryMenu) : AbstractWidget(menu) {
|
class LevelGaugeWidget(menu: MatteryMenu) : AbstractWidget(menu) {
|
||||||
|
@ -1,4 +0,0 @@
|
|||||||
package ru.dbotthepony.mc.otm.storage
|
|
||||||
|
|
||||||
import ru.dbotthepony.mc.otm.core.Fraction
|
|
||||||
import java.util.*
|
|
@ -3,7 +3,6 @@ package ru.dbotthepony.mc.otm.storage
|
|||||||
import ru.dbotthepony.mc.otm.capability.IMatteryEnergyStorage
|
import ru.dbotthepony.mc.otm.capability.IMatteryEnergyStorage
|
||||||
import ru.dbotthepony.mc.otm.core.Fraction
|
import ru.dbotthepony.mc.otm.core.Fraction
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.function.Supplier
|
|
||||||
|
|
||||||
class RemoteTuple<T : IStorageStack>(val obj: T, val remote_id: UUID, val provider: IStorageView<T>, val local: LocalTuple<T>) {
|
class RemoteTuple<T : IStorageStack>(val obj: T, val remote_id: UUID, val provider: IStorageView<T>, val local: LocalTuple<T>) {
|
||||||
fun extract(amount: Fraction, simulate: Boolean): T {
|
fun extract(amount: Fraction, simulate: Boolean): T {
|
||||||
|
@ -4,10 +4,9 @@ import org.junit.jupiter.api.DisplayName
|
|||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
import org.junit.jupiter.api.assertThrows
|
import org.junit.jupiter.api.assertThrows
|
||||||
import ru.dbotthepony.mc.otm.core.Fraction
|
import ru.dbotthepony.mc.otm.core.Fraction
|
||||||
import java.lang.Math.floor
|
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
import java.math.BigInteger
|
import java.math.BigInteger
|
||||||
import kotlin.random.Random
|
|
||||||
|
|
||||||
object FractionTests {
|
object FractionTests {
|
||||||
@Test
|
@Test
|
||||||
@ -138,6 +137,15 @@ object FractionTests {
|
|||||||
Fraction(1043, -648),
|
Fraction(1043, -648),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
private val samplesIM = arrayOf(
|
||||||
|
ImpreciseFraction(9475.0 / 4729),
|
||||||
|
ImpreciseFraction(23535.0 / 58723),
|
||||||
|
ImpreciseFraction(-4852.0 / 6859),
|
||||||
|
ImpreciseFraction(-45623.0 / -76849),
|
||||||
|
ImpreciseFraction(38494.0 / -76849),
|
||||||
|
ImpreciseFraction(1043.0 / -648),
|
||||||
|
)
|
||||||
|
|
||||||
private val samples2 = arrayOf(
|
private val samples2 = arrayOf(
|
||||||
(9475.0 / 4729),
|
(9475.0 / 4729),
|
||||||
(23535.0 / 58723),
|
(23535.0 / 58723),
|
||||||
@ -161,6 +169,7 @@ object FractionTests {
|
|||||||
fun performance() {
|
fun performance() {
|
||||||
val rand = java.util.Random()
|
val rand = java.util.Random()
|
||||||
val blackHole = arrayOfNulls<Fraction>(100_000)
|
val blackHole = arrayOfNulls<Fraction>(100_000)
|
||||||
|
val blackHoleIM = arrayOfNulls<ImpreciseFraction>(100_000)
|
||||||
val size = samples.size
|
val size = samples.size
|
||||||
var time = System.currentTimeMillis()
|
var time = System.currentTimeMillis()
|
||||||
|
|
||||||
@ -175,6 +184,19 @@ object FractionTests {
|
|||||||
|
|
||||||
println("Mean time for Fraction operation is ~${System.currentTimeMillis() - time} ms per 100,000 ops")
|
println("Mean time for Fraction operation is ~${System.currentTimeMillis() - time} ms per 100,000 ops")
|
||||||
|
|
||||||
|
time = System.currentTimeMillis()
|
||||||
|
|
||||||
|
for (i in 0 until 100_000) {
|
||||||
|
when (rand.nextInt(3)) {
|
||||||
|
0 -> blackHoleIM[i] = samplesIM[rand.nextInt(size)] + samplesIM[rand.nextInt(size)]
|
||||||
|
1 -> blackHoleIM[i] = samplesIM[rand.nextInt(size)] - samplesIM[rand.nextInt(size)]
|
||||||
|
2 -> blackHoleIM[i] = samplesIM[rand.nextInt(size)] * samplesIM[rand.nextInt(size)]
|
||||||
|
// 3 -> blackHole[i] = samples[rand.nextInt(size)] / samples[rand.nextInt(size)]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
println("Mean time for ImpreciseFraction operation is ~${System.currentTimeMillis() - time} ms per 100,000 ops")
|
||||||
|
|
||||||
var sum = Fraction.ZERO
|
var sum = Fraction.ZERO
|
||||||
|
|
||||||
// перемешаем чтоб оптимизатор не отбросил
|
// перемешаем чтоб оптимизатор не отбросил
|
||||||
@ -227,6 +249,14 @@ object FractionTests {
|
|||||||
blackHole3[i] = blackHole3[rand.nextInt(size)]
|
blackHole3[i] = blackHole3[rand.nextInt(size)]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var sum4 = 0.0
|
||||||
|
|
||||||
|
// перемешаем чтоб оптимизатор не отбросил
|
||||||
|
for (i in 0 until size) {
|
||||||
|
sum4 += blackHoleIM[i]!!.toDouble()
|
||||||
|
blackHoleIM[i] = blackHoleIM[rand.nextInt(size)]
|
||||||
|
}
|
||||||
|
|
||||||
println("$sum $sum2 $sum3")
|
println("$sum $sum2 $sum3")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,43 @@
|
|||||||
|
package ru.dbotthepony.mc.otm.tests
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.DisplayName
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
|
||||||
|
|
||||||
|
object ImpreciseFractionTests {
|
||||||
|
@Test
|
||||||
|
@DisplayName("ImpreciseFraction comparison")
|
||||||
|
fun comparison() {
|
||||||
|
check(ImpreciseFraction(642, 0.43774) > ImpreciseFraction(641, 0.43774)) { "must be bigger" }
|
||||||
|
check(ImpreciseFraction(642, 0.43774) > ImpreciseFraction(-641, 0.43774)) { "must be bigger" }
|
||||||
|
check(ImpreciseFraction(0) == ImpreciseFraction(0)) { "integer notation" }
|
||||||
|
check(ImpreciseFraction(0.1) > ImpreciseFraction(0)) { "must be bigger" }
|
||||||
|
check(ImpreciseFraction(-0.1) < ImpreciseFraction(0)) { "must be lesser" }
|
||||||
|
check(ImpreciseFraction(-1, -0.1) < ImpreciseFraction(-1)) { "must be lesser" }
|
||||||
|
check(ImpreciseFraction(0.1) == ImpreciseFraction(0.1)) { "double notation" }
|
||||||
|
check(ImpreciseFraction("0.1") == ImpreciseFraction("0.1")) { "string notation" }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("ImpreciseFraction mathematical operations")
|
||||||
|
fun math() {
|
||||||
|
check((ImpreciseFraction(1) + ImpreciseFraction(2)) == ImpreciseFraction(3)) { "1 + 2 != 3" }
|
||||||
|
check((ImpreciseFraction(0, 0.5) + ImpreciseFraction(0, 0.5)) == ImpreciseFraction(1)) { "0.5 + 0.5 != 1" }
|
||||||
|
check((ImpreciseFraction(0, 0.5) + ImpreciseFraction(0, -0.5)) == ImpreciseFraction(0)) { "0.5 + -0.5 != 1" }
|
||||||
|
check((ImpreciseFraction(0, 0.5) - ImpreciseFraction(0, -0.5)) == ImpreciseFraction(1)) { "0.5 - -0.5 != 1" }
|
||||||
|
check((ImpreciseFraction(0, 0.3) - ImpreciseFraction(1, 0.2)) == ImpreciseFraction(0, -0.9)) { "0.3 - 1.2 != -0.9" }
|
||||||
|
check((ImpreciseFraction(0, 0.3) * ImpreciseFraction(0, 0.3)) == ImpreciseFraction(0, 0.09)) { "0.3 * 0.3 != 0.9 ${ImpreciseFraction(0, 0.3) * ImpreciseFraction(0, 0.3)}" }
|
||||||
|
check((ImpreciseFraction(2, 0.3) * ImpreciseFraction(2, 0.3)) == ImpreciseFraction(5, 0.29)) { "2.3 * 2.3 != 5.29 ${ImpreciseFraction(2, 0.3) * ImpreciseFraction(2, 0.3)}" }
|
||||||
|
check((ImpreciseFraction(4) / ImpreciseFraction(2)) == ImpreciseFraction(2)) { "4 / 2 != 2" }
|
||||||
|
check((ImpreciseFraction(6) / ImpreciseFraction(2)) == ImpreciseFraction(3)) { "6 / 2 != 2" }
|
||||||
|
check((ImpreciseFraction(1) / ImpreciseFraction(0, 0.25)) == ImpreciseFraction(4)) { "1 / 0.25 != 4" }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("ImpreciseFraction store/load")
|
||||||
|
fun storeLoad() {
|
||||||
|
val f = ImpreciseFraction(4, 0.28)
|
||||||
|
val loaded = ImpreciseFraction.fromBytesArray(f.toBytesArray())
|
||||||
|
check(f == loaded) { "$f != $loaded" }
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user