add FixedEquiv trait

This commit is contained in:
Trevor Spiteri 2021-05-09 11:34:44 +02:00
parent 72a14433ef
commit 21933448b3
5 changed files with 130 additions and 14 deletions

View File

@ -112,6 +112,7 @@ The conversions supported cover the following cases.
* [`Signed`][tf-s-1-9], [`Unsigned`][tf-u-1-9]
* [`get_signed`][tf-gs-1-9], [`get_unsigned`][tf-gu-1-9]
* [`get_signed_mut`][tf-gsm-1-9], [`get_unsigned_mut`][tf-gum-1-9]
* The new trait [`FixedEquiv`][fe-1-9] was added.
* The following traits from the [*bytemuck* crate] were implemented for all
fixed-point numbers, added as supertraits to the [`Fixed`][tf-1-9] trait,
and implemented for the [`Wrapping`][w-1-9] and [`Unwrapped`][u-1-9]
@ -147,6 +148,7 @@ The conversions supported cover the following cases.
[f-ud-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/struct.FixedI32.html#method.unwrapped_dist
[f-unsd-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/struct.FixedI32.html#method.unsigned_dist
[f-wd-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/struct.FixedI32.html#method.wrapping_dist
[fe-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/traits/trait.FixedEquiv.html
[fof-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/traits/trait.FixedOptionalFeatures.html
[leu128-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/types/extra/trait.LeEqU128.html
[leu16-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/types/extra/trait.LeEqU16.html

View File

@ -28,6 +28,7 @@ Version 1.9.0 (unreleased)
* [`Signed`][tf-s-1-9], [`Unsigned`][tf-u-1-9]
* [`get_signed`][tf-gs-1-9], [`get_unsigned`][tf-gu-1-9]
* [`get_signed_mut`][tf-gsm-1-9], [`get_unsigned_mut`][tf-gum-1-9]
* The new trait [`FixedEquiv`][fe-1-9] was added.
* The following traits from the [*bytemuck* crate] were implemented for all
fixed-point numbers, added as supertraits to the [`Fixed`][tf-1-9] trait,
and implemented for the [`Wrapping`][w-1-9] and [`Unwrapped`][u-1-9]
@ -62,6 +63,7 @@ Compatibility notes
[f-ud-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/struct.FixedI32.html#method.unwrapped_dist
[f-unsd-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/struct.FixedI32.html#method.unsigned_dist
[f-wd-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/struct.FixedI32.html#method.wrapping_dist
[fe-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/traits/trait.FixedEquiv.html
[fof-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/traits/trait.FixedOptionalFeatures.html
[leu128-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/types/extra/trait.LeEqU128.html
[leu16-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/types/extra/trait.LeEqU16.html

View File

@ -95,7 +95,7 @@ x86_64-gnulinux-tarpaulin:
image: amd64/rust:1
variables:
TARGET: x86_64
REQ_COVERAGE: "78.4"
REQ_COVERAGE: "78"
cache:
key: $CI_JOB_NAME
paths:

View File

@ -15,9 +15,12 @@
use crate::{
helpers::{FloatHelper, FloatKind, FromFloatHelper, IntHelper},
traits::{Fixed, FromFixed, ToFixed},
F128Bits,
traits::{Fixed, FixedEquiv, FromFixed, ToFixed},
types::extra::U0,
F128Bits, FixedI128, FixedI16, FixedI32, FixedI64, FixedI8, FixedU128, FixedU16, FixedU32,
FixedU64, FixedU8,
};
use bytemuck::TransparentWrapper;
use half::{bf16, f16};
impl ToFixed for bool {
@ -80,7 +83,7 @@ impl ToFixed for bool {
}
macro_rules! impl_int {
($Int:ident) => {
($Int:ident $(, $Equiv:ident)?) => {
impl FromFixed for $Int {
/// Converts a fixed-point number to an integer.
///
@ -209,20 +212,56 @@ macro_rules! impl_int {
ToFixed::unwrapped_to_fixed(self.to_repr_fixed())
}
}
$(
impl FixedEquiv for $Int {
type Equiv = $Equiv<U0>;
#[inline]
fn to_fixed_equiv(self) -> $Equiv<U0> {
$Equiv::from_bits(self)
}
#[inline]
fn as_fixed_equiv(&self) -> &$Equiv<U0> {
$Equiv::wrap_ref(self)
}
#[inline]
fn as_fixed_equiv_mut(&mut self) -> &mut $Equiv<U0> {
$Equiv::wrap_mut(self)
}
#[inline]
fn from_fixed_equiv(f: $Equiv<U0>) -> $Int {
f.to_bits()
}
#[inline]
fn ref_from_fixed_equiv(f: &$Equiv<U0>) -> &$Int {
&f.bits
}
#[inline]
fn mut_from_fixed_equiv(f: &mut $Equiv<U0>) -> &mut $Int {
&mut f.bits
}
}
)*
};
}
impl_int! { i8 }
impl_int! { i16 }
impl_int! { i32 }
impl_int! { i64 }
impl_int! { i128 }
impl_int! { i8, FixedI8 }
impl_int! { i16, FixedI16 }
impl_int! { i32, FixedI32 }
impl_int! { i64, FixedI64 }
impl_int! { i128, FixedI128 }
impl_int! { isize }
impl_int! { u8 }
impl_int! { u16 }
impl_int! { u32 }
impl_int! { u64 }
impl_int! { u128 }
impl_int! { u8, FixedU8 }
impl_int! { u16, FixedU16 }
impl_int! { u32, FixedU32 }
impl_int! { u64, FixedU64 }
impl_int! { u128, FixedU128 }
impl_int! { usize }
macro_rules! impl_float {

View File

@ -2903,6 +2903,79 @@ pub trait ToFixed {
}
}
/// This trait provides a way to convert a number to/from an equivalent
/// fixed-point number.
///
/// Implementations are provided for the signed integer primitives [`i8`],
/// [`i16`], [`i32`], [`i64`] and [`i128`], which have equivalent fixed-point
/// types [`I8F0`], [`I16F0`], [`I32F0`], [`I64F0`] and [`I128F0`]. Similar
/// implementations are provided for the unsigned integer primitives [`u8`],
/// [`u16`], [`u32`], [`u64`] and [`u128`].
///
/// # Examples
///
/// An [`i32`] can be treated as an [`I32F0`].
///
/// ```rust
/// use fixed::traits::{Fixed, FixedEquiv};
///
/// fn next_up<F: Fixed>(f: &mut F) {
/// *f += F::DELTA;
/// }
///
/// let mut i = 12i32;
/// // next_up is called with &mut i converted to &mut I32F0
/// next_up(i.as_fixed_equiv_mut());
/// assert_eq!(i, 13);
/// ```
///
/// Simlarly, an [`I32F0`] can be treated as an [`i32`].
///
/// ```rust
/// use fixed::{traits::FixedEquiv, types::I32F0};
///
/// fn increase_by_5(i: &mut i32) {
/// *i += 5;
/// }
///
/// let mut f = I32F0::from_num(12);
/// // increase_by_5 is called with &mut f converted to &mut i32
/// increase_by_5(i32::mut_from_fixed_equiv(&mut f));
/// assert_eq!(f, 17);
/// ```
///
/// [`I8F0`]: crate::types::I8F0
/// [`I16F0`]: crate::types::I16F0
/// [`I32F0`]: crate::types::I32F0
/// [`I64F0`]: crate::types::I64F0
/// [`I128F0`]: crate::types::I128F0
pub trait FixedEquiv {
/// The equivalent fixed-point type.
type Equiv: Fixed;
/// Converts an owned value to the equivalent fixed-point type.
fn to_fixed_equiv(self) -> Self::Equiv;
/// Converts a reference into a reference to the equivalent fixed-point
/// type.
fn as_fixed_equiv(&self) -> &Self::Equiv;
/// Converts a mutable reference into a mutable reference to the equivalent
/// fixed-point type.
fn as_fixed_equiv_mut(&mut self) -> &mut Self::Equiv;
/// Converts an owned equivalent fixed-point type to this type.
fn from_fixed_equiv(f: Self::Equiv) -> Self;
/// Converts a reference to the equivalent fixed-point type into a reference
/// to this type.
fn ref_from_fixed_equiv(f: &Self::Equiv) -> &Self;
/// Converts a mutable reference to the equivalent fixed-point type into a
/// mutable reference to this type.
fn mut_from_fixed_equiv(f: &mut Self::Equiv) -> &mut Self;
}
macro_rules! trait_delegate {
(fn $method:ident($($param:ident: $Param:ty),*) -> $Ret:ty) => {
#[inline]