add examples to checked arithmetic operations

This commit is contained in:
Trevor Spiteri 2019-02-07 22:53:33 +01:00
parent bdf6f9fe88
commit 0352ba65a6
2 changed files with 286 additions and 65 deletions

View File

@ -511,7 +511,7 @@ assert_eq!(Fix::from_bits(bits).rotate_right(3), Fix::from_bits(rot));
$Fixed($Inner) => fn rotate_right(self, n: u32)
);
fixed_checked_arith! { $Fixed($Inner), $Signedness }
fixed_checked_arith! { $Fixed[$s_fixed]($Inner, $s_nbits), $Signedness }
if_unsigned! {
$Signedness;

View File

@ -14,26 +14,102 @@
// <https://opensource.org/licenses/MIT>.
macro_rules! fixed_checked_arith {
($Fixed:ident($Inner:ty), $Signedness:tt) => {
/// Checked negation.
($Fixed:ident[$s_fixed:expr]($Inner:ty, $s_nbits:expr), $Signedness:tt) => {
comment!(
"Checked negation. Returns the negated value, or [`None`] on overflow.
",
if_signed_unsigned!(
$Signedness,
"Overflow can only occur when negating the minimum value.",
"Only zero can be negated without overflow.",
),
"
# Examples
```rust
type Fix = fixed::",
$s_fixed,
"<fixed::frac::U4>;
",
if_signed_unsigned!(
$Signedness,
"assert_eq!(Fix::from_int(5).checked_neg(), Some(Fix::from_int(-5)));
assert_eq!(Fix::min_value().checked_neg(), None);",
"assert_eq!(Fix::from_int(0).checked_neg(), Some(Fix::from_int(0)));
assert_eq!(Fix::from_int(5).checked_neg(), None);",
),
"
```
[`None`]: https://doc.rust-lang.org/nightly/std/option/enum.Option.html#variant.None
";
#[inline]
pub fn checked_neg(self) -> Option<$Fixed<Frac>> {
<$Inner>::checked_neg(self.to_bits()).map(Self::from_bits)
}
);
/// Checked fixed-point addition.
comment!(
"Checked addition. Returns the sum, or [`None`] on overflow.
# Examples
```rust
type Fix = fixed::",
$s_fixed,
"<fixed::frac::U4>;
let one = Fix::from_int(1);
assert_eq!((Fix::max_value() - one).checked_add(one), Some(Fix::max_value()));
assert_eq!(Fix::max_value().checked_add(one), None);
```
[`None`]: https://doc.rust-lang.org/nightly/std/option/enum.Option.html#variant.None
";
#[inline]
pub fn checked_add(self, rhs: $Fixed<Frac>) -> Option<$Fixed<Frac>> {
<$Inner>::checked_add(self.to_bits(), rhs.to_bits()).map(Self::from_bits)
}
);
/// Checked fixed-point subtraction.
comment!(
"Checked subtraction. Returns the difference, or [`None`] on overflow.
# Examples
```rust
type Fix = fixed::",
$s_fixed,
"<fixed::frac::U4>;
let one = Fix::from_int(1);
assert_eq!((Fix::min_value() + one).checked_sub(one), Some(Fix::min_value()));
assert_eq!(Fix::min_value().checked_sub(one), None);
```
[`None`]: https://doc.rust-lang.org/nightly/std/option/enum.Option.html#variant.None
";
#[inline]
pub fn checked_sub(self, rhs: $Fixed<Frac>) -> Option<$Fixed<Frac>> {
<$Inner>::checked_sub(self.to_bits(), rhs.to_bits()).map(Self::from_bits)
}
);
/// Checked fixed-point multiplication.
comment!(
"Checked multiplication. Returns the product, or [`None`] on overflow.
# Examples
```rust
type Fix = fixed::",
$s_fixed,
"<fixed::frac::U4>;
assert_eq!(Fix::max_value().checked_mul(Fix::from_int(1)), Some(Fix::max_value()));
assert_eq!(Fix::max_value().checked_mul(Fix::from_int(2)), None);
```
[`None`]: https://doc.rust-lang.org/nightly/std/option/enum.Option.html#variant.None
";
#[inline]
pub fn checked_mul(self, rhs: $Fixed<Frac>) -> Option<$Fixed<Frac>> {
let (ans, dir) = self.to_bits().mul_dir(rhs.to_bits(), Frac::U32);
@ -42,8 +118,24 @@ macro_rules! fixed_checked_arith {
_ => None,
}
}
);
/// Checked fixed-point division.
comment!(
"Checked division. Returns the quotient, or [`None`] if
the divisor is zero or on overflow.
# Examples
```rust
type Fix = fixed::",
$s_fixed,
"<fixed::frac::U4>;
assert_eq!(Fix::max_value().checked_div(Fix::from_int(1)), Some(Fix::max_value()));
assert_eq!(Fix::max_value().checked_div(Fix::from_int(1) / 2), None);
```
[`None`]: https://doc.rust-lang.org/nightly/std/option/enum.Option.html#variant.None
";
#[inline]
pub fn checked_div(self, rhs: $Fixed<Frac>) -> Option<$Fixed<Frac>> {
if rhs.to_bits() == 0 {
@ -55,44 +147,173 @@ macro_rules! fixed_checked_arith {
_ => None,
}
}
);
/// Checked fixed-point multiplication by integer.
comment!(
"Checked multiplication by an integer. Returns the
product, or [`None`] on overflow.
# Examples
```rust
type Fix = fixed::",
$s_fixed,
"<fixed::frac::U4>;
assert_eq!(Fix::max_value().checked_mul_int(1), Some(Fix::max_value()));
assert_eq!(Fix::max_value().checked_mul_int(2), None);
```
[`None`]: https://doc.rust-lang.org/nightly/std/option/enum.Option.html#variant.None
";
#[inline]
pub fn checked_mul_int(self, rhs: $Inner) -> Option<$Fixed<Frac>> {
<$Inner>::checked_mul(self.to_bits(), rhs).map(Self::from_bits)
}
);
/// Checked fixed-point division by integer.
comment!(
"Checked division by an integer. Returns the quotient, or
[`None`] if the divisor is zero",
if_signed_unsigned!(
$Signedness,
" or if the division results in overflow.",
".",
),
"
# Examples
```rust
type Fix = fixed::",
$s_fixed,
"<fixed::frac::U4>;
assert_eq!(Fix::max_value().checked_div_int(1), Some(Fix::max_value()));
assert_eq!(Fix::from_int(1).checked_div_int(0), None);
",
if_signed_else_empty_str!(
$Signedness,
"assert_eq!(Fix::min_value().checked_div_int(-1), None);
",
),
"```
[`None`]: https://doc.rust-lang.org/nightly/std/option/enum.Option.html#variant.None
";
#[inline]
pub fn checked_div_int(self, rhs: $Inner) -> Option<$Fixed<Frac>> {
<$Inner>::checked_div(self.to_bits(), rhs).map(Self::from_bits)
}
);
/// Checked fixed-point remainder for division by integer.
comment!(
"Checked fixed-point remainder for division by an integer.
Returns the remainder, or [`None`] if the divisor is zero",
if_signed_unsigned!(
$Signedness,
" or if the division results in overflow.",
".",
),
"
# Examples
```rust
type Fix = fixed::",
$s_fixed,
"<fixed::frac::U4>;
// binary 1.0101 / 8 = binary 0.0010 remainder 0.0101
assert_eq!(Fix::from_bits(0b10101).checked_rem_int(8), Some(Fix::from_bits(0b101)));
assert_eq!(Fix::from_int(1).checked_rem_int(0), None);
",
if_signed_else_empty_str!(
$Signedness,
"assert_eq!(Fix::min_value().checked_rem_int(-1), None);
",
),
"```
[`None`]: https://doc.rust-lang.org/nightly/std/option/enum.Option.html#variant.None
";
#[inline]
pub fn checked_rem_int(self, rhs: $Inner) -> Option<$Fixed<Frac>> {
<$Inner>::checked_rem(self.to_bits(), rhs).map(Self::from_bits)
}
);
/// Checked fixed-point left shift.
comment!(
"Checked shift left. Returns the shifted number, or [`None`] if `rhs` ≥ ",
$s_nbits,
".
# Examples
```rust
type Fix = fixed::",
$s_fixed,
"<fixed::frac::U4>;
assert_eq!((Fix::from_int(1) / 2).checked_shl(3), Some(Fix::from_int(4)));
assert_eq!((Fix::from_int(1) / 2).checked_shl(",
$s_nbits,
"), None);
```
[`None`]: https://doc.rust-lang.org/nightly/std/option/enum.Option.html#variant.None
";
#[inline]
pub fn checked_shl(self, rhs: u32) -> Option<$Fixed<Frac>> {
<$Inner>::checked_shl(self.to_bits(), rhs).map(Self::from_bits)
}
);
/// Checked fixed-point right shift.
comment!(
"Checked shift right. Returns the shifted number, or [`None`] if `rhs` ≥ ",
$s_nbits,
".
# Examples
```rust
type Fix = fixed::",
$s_fixed,
"<fixed::frac::U4>;
assert_eq!(Fix::from_int(4).checked_shr(3), Some(Fix::from_int(1) / 2));
assert_eq!(Fix::from_int(4).checked_shr(",
$s_nbits,
"), None);
```
[`None`]: https://doc.rust-lang.org/nightly/std/option/enum.Option.html#variant.None
";
#[inline]
pub fn checked_shr(self, rhs: u32) -> Option<$Fixed<Frac>> {
<$Inner>::checked_shr(self.to_bits(), rhs).map(Self::from_bits)
}
);
if_signed! {
$Signedness;
/// Checked absolute value.
comment!(
"Checked absolute value. Returns the absolute value, or [`None`] on overflow.
Overflow can only occur when trying to find the absolute value of the minimum value.
# Examples
```rust
type Fix = fixed::",
$s_fixed,
"<fixed::frac::U4>;
assert_eq!(Fix::from_int(-5).checked_abs(), Some(Fix::from_int(5)));
assert_eq!(Fix::min_value().checked_abs(), None);
```
[`None`]: https://doc.rust-lang.org/nightly/std/option/enum.Option.html#variant.None
";
#[inline]
pub fn checked_abs(self) -> Option<$Fixed<Frac>> {
<$Inner>::checked_abs(self.to_bits()).map(Self::from_bits)
}
);
}
/// Saturating fixed-point addition.