Raising Rational Fractions to Integer Powers
Closed this issue · 4 comments
I use this function to exponentiate rational fractions. Simply: (a/b)^c
Any chance we can add this into the library?
/// Integer Power: a rational fraction, x, raised to the integer power y.
///
/// ```aiken
/// expect Some(x) = rational.new(50, 2500)
/// let y = 3
///
/// Some(rational.int_power(x, y)) == rational.new(1, 125000)
/// ```
pub fn int_power(x: Rational, y: Int) -> Rational {
let Rational { numerator: a, denominator: b } = x
if y > 0 {
Rational { numerator: math.pow(a, y), denominator: math.pow(b, y) }
} else if y < 0 {
Rational { numerator: math.pow(b, math.abs(y)), denominator: math.pow(a, math.abs(y)) }
} else {
Rational { numerator: 1, denominator: 1 }
}
}
With some tests:
test int_power_neg() {
expect Some(x) = rational.new(50, 2500)
let y = -3
expect Some(z) = rational.new(125000, 1)
rational.reduce(rational.int_power(x, y)) == z
}
test int_power_pos() {
expect Some(x) = rational.new(50, 2500)
let y = 3
expect Some(z) = rational.new(1, 125000)
rational.reduce(rational.int_power(x, y)) == z
}
test int_power_zero() {
expect Some(x) = rational.new(50, 2500)
let y = 0
expect Some(z) = rational.new(1, 1)
rational.reduce(rational.int_power(x, y)) == z
}
You need some additional checks to make this work. If y is negative and a is zero then you are allowing 1/0 to occur and if a is zero and y is zero then you are saying 0^0 is 1.
As a side note: I don't see strong reasons not to add such a function. Though I agree with @logicalmechanism, the test coverage is pretty thin. We could also leverage prop tests here.
Ah yes, nice catch. I actually had a more robust version of this with more test cases, but I unwisely let it live in the rational.ak
file. And after bumping the std-lib
it got overwritten and lost it lol. And enough time had past where I mostly forgot what I did. Hence the motivation to get this in there natively. I have some pockets of time in next 2 weeks I can use to improve this.