I get the following warning in Intellij Idea (build: 173.3727.127, Kotlin plugin: latest): Kotlin: Unreachable Code for the code (in line 4: return when (a) {):
fun pow(a: Number, b: Int): Number {
if (b == 0) return 1
if (b == 1) return a
return when (a) {
is Long -> {
return if (b % 2 == 0) pow(a * a, b / 2)
else a * pow(a * a, b / 2) as Long
}
is Int -> {
return if (b % 2 == 0) pow(a * a, b / 2)
else a * pow(a * a, b / 2) as Int
}
is BigInteger -> {
return if (b % 2 == 0) pow(a * a, b / 2)
else a * pow(a * a, b / 2) as BigInteger
}
else -> throw IllegalArgumentException("only Long, Int, BigInteger are supported")
}
}
The code works fine for Long, Int, and BigInteger as expected.
This tail recursive implementation will perform better and does not blow up the stack and does not keep repeatedly keep checking the type of the value (hopefully I got the math correct):
fun pow(a: Number, b: Int): Number
{
tailrec fun pow(a: Int, b: Int, product: Int = 1) : Int
= when
{
b == 0 -> product
b == 1 -> a * product
b % 2 == 0 -> pow(a * a, b / 2, product)
else -> pow(a * a, b / 2, a * product)
}
tailrec fun pow(a: Long, b: Int, product: Long = 1L) : Long
= when
{
b == 0 -> product
b == 1 -> a * product
b % 2 == 0 -> pow(a * a, b / 2, product)
else -> pow(a * a, b / 2, a * product)
}
tailrec fun pow(a: BigInteger, b: Int, product: BigInteger = BigInteger.ONE) : BigInteger
= when
{
b == 0 -> product
b == 1 -> a * product
b % 2 == 0 -> pow(a * a, b / 2, product)
else -> pow(a * a, b / 2, a * product)
}
return when
{
b < 0 -> throw IllegalArgumentException("negative exponent not supported")
a is Long -> pow(a, b)
a is Int -> pow(a, b)
a is BigInteger -> pow(a, b)
else -> throw IllegalArgumentException("only Long, Int, BigInteger are supported")
}
}