Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pow(0, 0) no longer returnes 1 #78

Closed
wants to merge 3 commits into from
Closed
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 30 additions & 5 deletions src/pow.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use core::num::Wrapping;
use core::ops::Mul;
use {CheckedMul, One};
use {CheckedMul, One, Zero};

/// Binary operator for raising a value to a power.
pub trait Pow<RHS> {
Expand Down Expand Up @@ -172,6 +172,7 @@ mod float_impls {
}

/// Raises a value to the power of exp, using exponentiation by squaring.
/// Panics if pow(0, 0) (0⁰ is undefined)
///
/// # Example
///
Expand All @@ -182,9 +183,13 @@ mod float_impls {
/// assert_eq!(pow(6u8, 3), 216);
/// ```
#[inline]
pub fn pow<T: Clone + One + Mul<T, Output = T>>(mut base: T, mut exp: usize) -> T {
pub fn pow<T: Clone + Zero + One + Mul<T, Output = T>>(mut base: T, mut exp: usize) -> T {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe that this is breaking change, so we should think if this is really only way.

if exp == 0 {
return T::one();
return if base.is_zero() {
panic!("0⁰ is undefined")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would restrain myself from using Unicode in panic messages as it can be problematic on platforms that do not support Unicode in CLI (aka Windows).

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we want:

  • 0^0
  • pow(0, 0)
  • any other?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would go with pow(0, 0) as this is what user wrote. 0^0 is common syntax but in this case can be confused with XOR operator.

} else {
T::one()
};
}

while exp & 1 == 0 {
Expand All @@ -207,6 +212,7 @@ pub fn pow<T: Clone + One + Mul<T, Output = T>>(mut base: T, mut exp: usize) ->
}

/// Raises a value to the power of exp, returning `None` if an overflow occurred.
/// Also returns None if checked_pow(0, 0) was entered (0⁰ is undefined)
///
/// Otherwise same as the `pow` function.
///
Expand All @@ -218,11 +224,12 @@ pub fn pow<T: Clone + One + Mul<T, Output = T>>(mut base: T, mut exp: usize) ->
/// assert_eq!(checked_pow(2i8, 4), Some(16));
/// assert_eq!(checked_pow(7i8, 8), None);
/// assert_eq!(checked_pow(7u32, 8), Some(5_764_801));
/// assert_eq!(checked_pow(0i8, 0), None); //undefined
/// ```
#[inline]
pub fn checked_pow<T: Clone + One + CheckedMul>(mut base: T, mut exp: usize) -> Option<T> {
pub fn checked_pow<T: Clone + Zero + One + CheckedMul>(mut base: T, mut exp: usize) -> Option<T> {
if exp == 0 {
return Some(T::one());
return if base.is_zero() { None } else { Some(T::one()) };
}

macro_rules! optry {
Expand Down Expand Up @@ -253,3 +260,21 @@ pub fn checked_pow<T: Clone + One + CheckedMul>(mut base: T, mut exp: usize) ->
}
Some(acc)
}

#[cfg(test)]
mod tests {
#[test]
fn pow_3_3() {
assert_eq!(super::checked_pow(3, 3), Some(27));
assert_eq!(super::pow(3, 3), 27);
}
#[test]
fn checked_pow_0_0() {
assert_eq!(super::checked_pow(0, 0), None);
}
#[test]
#[should_panic]
fn pow_0_0() {
super::pow(0, 0);
}
}