1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249
use crate::convert::UncheckedFrom;
// todo: const trait implementations
// todo: maybe default implementations should not require `Self` traits
/// Provides a base implementation for what a `NonStandardInteger` needs.
pub trait NonStandardInteger<T, const BITS: u32>
where
T: PartialOrd + Copy,
Self: UncheckedFrom<T>,
{
// TODO: find a better name for this.
/// The underlying representation of the integer.
type Repr = T;
/// The size of this integer type in bits.
const BITS: u32 = BITS;
/// The smallest value that can be represented by this integer type.
const MIN: T;
/// The largest value that can be represented by this integer type.
const MAX: T;
/// Returns the smallest value that can be represented by this integer type.
fn min_value() -> Self;
/// Returns the largest value that can be represented by this integer type.
fn max_value() -> Self;
}
/// Provides integer methods.
pub trait NonStandardIntegerCommon<T: PartialOrd + Copy, const BITS: u32>
where
Self: NonStandardInteger<T, BITS>,
{
/// Checked integer addition. Computes `self + rhs`, returning [`None`]
/// if overflow occurred.
fn checked_add(self, rhs: Self) -> Option<Self>;
/// Checked integer subtraction. Computes `self - rhs`, returning [`None`]
/// if overflow occurred.
fn checked_sub(self, rhs: Self) -> Option<Self>;
/// Checked integer multiplication. Computes `self * rhs`, returning [`None`]
/// if overflow occurred.
fn checked_mul(self, rhs: Self) -> Option<Self>;
/// Checked integer division. Computes `self / rhs`, returning [`None`]
/// if `rhs == 0`.
fn checked_div(self, rhs: Self) -> Option<Self>;
/// Checked integer remainder. Computes `self % rhs`, returning [`None`]
/// if `rhs == 0`.
fn checked_rem(self, rhs: Self) -> Option<Self>;
/// Checked shift left. Computes `self << rhs`, returning [`None`]
/// if `rhs` is larger than or equal to the number of bits in `self`.
fn checked_shl(self, rhs: u32) -> Option<Self>;
/// Checked shift right. Computes `self >> rhs`, returning [`None`]
/// if `rhs` is larger than or equal to the number of bits in `self`.
fn checked_shr(self, rhs: u32) -> Option<Self>;
// fn checked_pow(self, rhs: u32) -> Self;
/// Saturating integer addition. Computes `self + rhs`, saturating at the numeric bounds instead of overflowing.
fn saturating_add(self, rhs: Self) -> Self;
/// Saturating integer subtraction. Computes `self - rhs`, saturating at the numeric bounds instead of overflowing.
fn saturating_sub(self, rhs: Self) -> Self;
/// Saturating integer multiplication. Computes `self * rhs`, saturating at the numeric bounds instead of overflowing.
fn saturating_mul(self, rhs: Self) -> Self;
/// Saturating integer exponentiation. Computes `self.pow(exp)`, saturating at the numeric bounds instead of overflowing.
fn saturating_pow(self, exp: u32) -> Self;
/// Wrapping (modular) addition. Computes `self + rhs`, wrapping around at the
/// boundary of the type.
fn wrapping_add(self, rhs: Self) -> Self;
/// Wrapping (modular) subtraction. Computes `self - rhs`, wrapping around at the
/// boundary of the type.
fn wrapping_sub(self, rhs: Self) -> Self;
/// Wrapping (modular) multiplication. Computes `self * rhs`, wrapping around at
/// the boundary of the type.
fn wrapping_mul(self, rhs: Self) -> Self;
/// Wrapping (modular) division. Computes `self / rhs`, wrapping around at the
/// boundary of the type.
///
/// The only case where such wrapping can occur is when one divides `MIN / -1` on a signed type (where
/// [`MIN`](NonStandardInteger::MIN) is the negative minimal value for the type); this is equivalent to `-MIN`, a positive value
/// that is too large to represent in the type. In such a case, this function returns [`MIN`](NonStandardInteger::MIN) itself.
///
/// # Panics
///
/// This function will panic if `rhs` is 0.
fn wrapping_div(self, rhs: Self) -> Self;
/// Wrapping (modular) remainder. Computes `self % rhs`, wrapping around at the
/// boundary of the type.
///
/// Such wrap-around never actually occurs mathematically;
/// implementation artifacts make `x % y` invalid for `MIN / -1` on a signed type (where [`MIN`](NonStandardInteger::MIN) is the negative minimal value).
/// In such a case, this function returns `0`.
///
/// # Panics
///
/// This function will panic if `rhs` is 0.
fn wrapping_rem(self, rhs: Self) -> Self;
/// Panic-free bitwise shift-left; yields `self << mask(rhs)`,
/// where `mask` removes any high-order bits of `rhs` that
/// would cause the shift to exceed the bitwidth of the type.
fn wrapping_shl(self, rhs: u32) -> Self;
/// Panic-free bitwise shift-right; yields `self >> mask(rhs)`,
/// where `mask` removes any high-order bits of `rhs` that
/// would cause the shift to exceed the bitwidth of the type.
fn wrapping_shr(self, rhs: u32) -> Self;
// fn wrapping_pow(self, exp: u32) -> Self;
/// Calculates `self` + `rhs`
///
/// Returns a tuple of the addition along with a boolean indicating whether an arithmetic overflow would
/// occur. If an overflow would have occurred then the wrapped value is returned.
fn overflowing_add(self, rhs: Self) -> (Self, bool);
/// Calculates `self` - `rhs`
///
/// Returns a tuple of the subtraction along with a boolean indicating whether an arithmetic overflow
/// would occur. If an overflow would have occurred then the wrapped value is returned.
fn overflowing_sub(self, rhs: Self) -> (Self, bool);
/// Calculates the multiplication of `self` and `rhs`.
///
/// Returns a tuple of the multiplication along with a boolean indicating whether an arithmetic overflow
/// would occur. If an overflow would have occurred then the wrapped value is returned.
fn overflowing_mul(self, rhs: Self) -> (Self, bool);
/// Calculates the divisor when `self` is divided by `rhs`.
///
/// Returns a tuple of the divisor along with a boolean indicating whether an arithmetic overflow would
/// occur. If an overflow would occur then self is returned.
///
/// # Panics
///
/// This function will panic if `rhs` is 0.
fn overflowing_div(self, rhs: Self) -> (Self, bool);
/// Calculates the remainder when `self` is divided by `rhs`.
///
/// Returns a tuple of the remainder after dividing along with a boolean indicating whether an
/// arithmetic overflow would occur. If an overflow would occur then 0 is returned.
///
/// # Panics
///
/// This function will panic if `rhs` is 0.
fn overflowing_rem(self, rhs: Self) -> (Self, bool);
/// Shifts self left by `rhs` bits.
///
/// Returns a tuple of the shifted version of self along with a boolean
/// indicating whether the shift value was larger than or equal to the
/// number of bits. If the shift value is too large, then value is
/// masked `(BITS - 1)` where N is the number of bits, and this value is then
/// used to perform the shift.
fn overflowing_shl(self, rhs: u32) -> (Self, bool);
/// Shifts self right by `rhs` bits.
///
/// Returns a tuple of the shifted version of self along with a boolean
/// indicating whether the shift value was larger than or equal to the
/// number of bits. If the shift value is too large, then value is
/// masked `(BITS - 1)`, and this value is then
/// used to perform the shift.
fn overflowing_shr(self, rhs: u32) -> (Self, bool);
// fn overflowing_pow(self, exp: u32) -> Self;
}
/// Provides integer methods that only make sense with signed integers.
pub trait NonStandardIntegerSigned<T: PartialOrd + Copy, const BITS: u32>
where
Self: NonStandardInteger<T, BITS>,
{
/// Computes the absolute value of `self`.
///
/// # Overflow behavior
///
/// The absolute value of [`MIN`](NonStandardInteger::MIN) cannot be represented as a value in signed integers.
///
/// Attempting to calculate it will cause an overflow. This means
/// that code in debug mode will trigger a panic on this case and
/// optimized code will return [`MIN`](NonStandardInteger::MIN) without a panic.
fn abs(self) -> Self;
/// Returns `true` if `self` is negative and `false` if the number is zero or
/// positive.
fn is_negative(self) -> bool;
/// Saturating integer negation. Computes `-self`, returning [`MAX`](NonStandardInteger::MAX)
/// if `self == MIN` instead of overflowing.
fn saturating_neg(self) -> Self;
/// Saturating absolute value. Computes [`self.abs()`](Self::abs), returning [`MAX`](NonStandardInteger::MAX)
/// if `self == MIN` instead of overflowing.
fn saturating_abs(self) -> Self;
/// Negates self, overflowing if this is equal to the minimum value.
///
/// Returns a tuple of the negated version of self along with a boolean indicating whether an overflow
/// happened. If `self` is the minimum value [`MIN`](NonStandardInteger::MIN), then the
/// minimum value will be returned again and [`true`] will be returned for an overflow happening.
fn overflowing_neg(self) -> (Self, bool);
/// Computes the absolute value of `self`.
///
/// Returns a tuple of the absolute version of self along with a boolean indicating whether an overflow
/// happened. If self is the minimum value [`MIN`](NonStandardInteger::MIN) then the value will be returned
/// again and [`true`] will be returned for an overflow happening.
fn overflowing_abs(self) -> (Self, bool);
/// Checked negation. Computes `-self`, returning [`None`] if `self == MIN`.
fn checked_neg(self) -> Option<Self>;
/// Checked absolute value. Computes [`self.abs()`](Self::abs), returning [`None`] if
/// `self == MIN`
fn checked_abs(self) -> Option<Self>;
/// Wrapping (modular) negation. Computes `-self`, wrapping around at the boundary
/// of the type.
///
/// The only case where such wrapping can occur is when one negates[`MIN`](NonStandardInteger::MIN) on a signed type (where [`MIN`](NonStandardInteger::MIN)
/// is the negative minimal value for the type); this is a positive value that is too large to represent
/// in the type. In such a case, this function returns [`MIN`](NonStandardInteger::MIN) itself.
fn wrapping_neg(self) -> Self;
/// Wrapping (modular) absolute value. Computes [`self.abs()`](Self::abs), wrapping around at
/// the boundary of the type.
///
/// The only case where such wrapping can occur is when one takes the absolute value of the negative
/// minimal value for the type; this is a positive value that is too large to represent in the type. In
/// such a case, this function returns [`MIN`](NonStandardInteger::MIN) itself.
fn wrapping_abs(self) -> Self;
}