forked from kscience/kmath
Fast power is added
This commit is contained in:
parent
f67cfcc9e6
commit
1716b7f5d1
@ -15,15 +15,13 @@ import space.kscience.kmath.operations.BigIntField
|
|||||||
import space.kscience.kmath.operations.JBigIntegerField
|
import space.kscience.kmath.operations.JBigIntegerField
|
||||||
import space.kscience.kmath.operations.invoke
|
import space.kscience.kmath.operations.invoke
|
||||||
|
|
||||||
private fun BigInt.pow(power: Int): BigInt = modPow(BigIntField.number(power), BigInt.ONE)
|
|
||||||
|
|
||||||
|
|
||||||
@State(Scope.Benchmark)
|
@State(Scope.Benchmark)
|
||||||
internal class BigIntBenchmark {
|
internal class BigIntBenchmark {
|
||||||
|
|
||||||
val kmNumber = BigIntField.number(Int.MAX_VALUE)
|
val kmNumber = BigIntField.number(Int.MAX_VALUE)
|
||||||
val jvmNumber = JBigIntegerField.number(Int.MAX_VALUE)
|
val jvmNumber = JBigIntegerField.number(Int.MAX_VALUE)
|
||||||
val largeKmNumber = BigIntField { number(11).pow(100_000) }
|
val largeKmNumber = BigIntField { number(11).pow(100_000UL) }
|
||||||
val largeJvmNumber = JBigIntegerField { number(11).pow(100_000) }
|
val largeJvmNumber = JBigIntegerField { number(11).pow(100_000) }
|
||||||
val bigExponent = 50_000
|
val bigExponent = 50_000
|
||||||
|
|
||||||
@ -59,7 +57,7 @@ internal class BigIntBenchmark {
|
|||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
fun kmPower(blackhole: Blackhole) = BigIntField {
|
fun kmPower(blackhole: Blackhole) = BigIntField {
|
||||||
blackhole.consume(kmNumber.pow(bigExponent))
|
blackhole.consume(kmNumber.pow(bigExponent.toULong()))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
|
@ -250,6 +250,21 @@ public interface Ring<T> : Group<T>, RingOperations<T> {
|
|||||||
* neutral operation for multiplication
|
* neutral operation for multiplication
|
||||||
*/
|
*/
|
||||||
public val one: T
|
public val one: T
|
||||||
|
|
||||||
|
public fun T.pow(exponent: ULong): T = when {
|
||||||
|
this == zero && exponent > 0UL -> zero
|
||||||
|
this == one -> this
|
||||||
|
else -> powWithoutOptimization(exponent)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun T.powWithoutOptimization(exponent: ULong): T = when (exponent) {
|
||||||
|
0UL -> one
|
||||||
|
1UL -> this
|
||||||
|
else -> {
|
||||||
|
val pre = powWithoutOptimization(exponent shr 1).let { it * it }
|
||||||
|
if (exponent and 1UL == 0UL) pre else pre * this
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
package space.kscience.kmath.operations
|
package space.kscience.kmath.operations
|
||||||
|
|
||||||
import space.kscience.kmath.testutils.RingVerifier
|
import space.kscience.kmath.testutils.RingVerifier
|
||||||
|
import kotlin.math.pow
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
@ -21,6 +22,19 @@ internal class BigIntAlgebraTest {
|
|||||||
assertEquals(res, 1_000_000.toBigInt())
|
assertEquals(res, 1_000_000.toBigInt())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testKBigIntegerRingPow() {
|
||||||
|
BigIntField {
|
||||||
|
for (num in 0..5)
|
||||||
|
for (exponent in 0UL..10UL)
|
||||||
|
assertEquals(
|
||||||
|
num.toDouble().pow(exponent.toInt()).toLong().toBigInt(),
|
||||||
|
num.toBigInt().pow(exponent),
|
||||||
|
"$num ^ $exponent"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testKBigIntegerRingSum_100_000_000__100_000_000() {
|
fun testKBigIntegerRingSum_100_000_000__100_000_000() {
|
||||||
BigIntField {
|
BigIntField {
|
||||||
|
Loading…
Reference in New Issue
Block a user