104: Add inplace methods to `Zero` and `One` r=cuviper a=lcnr

Adds the following default implemented methods to `Zero` and `One`:

```rust
fn set_zero(&mut self) {
    *self = Zero::zero();
}
```

```rust
fn set_one(&mut self) {
    *self = One::one();
}
```

This allows for reuse of BigNums.


Co-authored-by: lcnr/Bastian Kauschke <bastian_kauschke@hotmail.de>
Co-authored-by: Josh Stone <cuviper@gmail.com>
This commit is contained in:
bors[bot] 2019-03-28 19:31:51 +00:00
commit 5404658360
1 changed files with 37 additions and 15 deletions

View File

@ -2,16 +2,15 @@ use core::num::Wrapping;
use core::ops::{Add, Mul}; use core::ops::{Add, Mul};
/// Defines an additive identity element for `Self`. /// Defines an additive identity element for `Self`.
///
/// # Laws
///
/// ```{.text}
/// a + 0 = a ∀ a ∈ Self
/// 0 + a = a ∀ a ∈ Self
/// ```
pub trait Zero: Sized + Add<Self, Output = Self> { pub trait Zero: Sized + Add<Self, Output = Self> {
/// Returns the additive identity element of `Self`, `0`. /// Returns the additive identity element of `Self`, `0`.
///
/// # Laws
///
/// ```{.text}
/// a + 0 = a ∀ a ∈ Self
/// 0 + a = a ∀ a ∈ Self
/// ```
///
/// # Purity /// # Purity
/// ///
/// This function should return the same result at all times regardless of /// This function should return the same result at all times regardless of
@ -20,6 +19,11 @@ pub trait Zero: Sized + Add<Self, Output = Self> {
// This cannot be an associated constant, because of bignums. // This cannot be an associated constant, because of bignums.
fn zero() -> Self; fn zero() -> Self;
/// Sets `self` to the additive identity element of `Self`, `0`.
fn set_zero(&mut self) {
*self = Zero::zero();
}
/// Returns `true` if `self` is equal to the additive identity. /// Returns `true` if `self` is equal to the additive identity.
#[inline] #[inline]
fn is_zero(&self) -> bool; fn is_zero(&self) -> bool;
@ -66,22 +70,27 @@ where
fn is_zero(&self) -> bool { fn is_zero(&self) -> bool {
self.0.is_zero() self.0.is_zero()
} }
fn set_zero(&mut self) {
self.0.set_zero();
}
fn zero() -> Self { fn zero() -> Self {
Wrapping(T::zero()) Wrapping(T::zero())
} }
} }
/// Defines a multiplicative identity element for `Self`. /// Defines a multiplicative identity element for `Self`.
///
/// # Laws
///
/// ```{.text}
/// a * 1 = a ∀ a ∈ Self
/// 1 * a = a ∀ a ∈ Self
/// ```
pub trait One: Sized + Mul<Self, Output = Self> { pub trait One: Sized + Mul<Self, Output = Self> {
/// Returns the multiplicative identity element of `Self`, `1`. /// Returns the multiplicative identity element of `Self`, `1`.
/// ///
/// # Laws
///
/// ```{.text}
/// a * 1 = a ∀ a ∈ Self
/// 1 * a = a ∀ a ∈ Self
/// ```
///
/// # Purity /// # Purity
/// ///
/// This function should return the same result at all times regardless of /// This function should return the same result at all times regardless of
@ -90,6 +99,11 @@ pub trait One: Sized + Mul<Self, Output = Self> {
// This cannot be an associated constant, because of bignums. // This cannot be an associated constant, because of bignums.
fn one() -> Self; fn one() -> Self;
/// Sets `self` to the multiplicative identity element of `Self`, `1`.
fn set_one(&mut self) {
*self = One::one();
}
/// Returns `true` if `self` is equal to the multiplicative identity. /// Returns `true` if `self` is equal to the multiplicative identity.
/// ///
/// For performance reasons, it's best to implement this manually. /// For performance reasons, it's best to implement this manually.
@ -111,6 +125,10 @@ macro_rules! one_impl {
fn one() -> $t { fn one() -> $t {
$v $v
} }
#[inline]
fn is_one(&self) -> bool {
*self == $v
}
} }
}; };
} }
@ -138,6 +156,10 @@ impl<T: One> One for Wrapping<T>
where where
Wrapping<T>: Mul<Output = Wrapping<T>>, Wrapping<T>: Mul<Output = Wrapping<T>>,
{ {
fn set_one(&mut self) {
self.0.set_one();
}
fn one() -> Self { fn one() -> Self {
Wrapping(T::one()) Wrapping(T::one())
} }