From aadbcaceb3995c946f510f753d153c747535355d Mon Sep 17 00:00:00 2001 From: Trevor Spiteri Date: Wed, 5 May 2021 19:49:21 +0200 Subject: [PATCH] add Fixed::get_{signed,unsigned}{,_mut} --- README.md | 9 +++- RELEASES.md | 9 +++- etc/gitlab-ci.yml | 2 +- src/traits.rs | 116 +++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 132 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index fc733b3..e68b5f3 100644 --- a/README.md +++ b/README.md @@ -107,8 +107,11 @@ The conversions supported cover the following cases. [`overflowing_distance`][f-od-1-9] * The [`unsigned_distance`][f-unsd-1-9] method was added to all signed fixed-point types and to the [`FixedSigned`][tfs-1-9] trait. - * The following associated types were added to the [`Fixed`][tf-1-9] trait: + * The following associated types and provided methods were added to the + [`Fixed`][tf-1-9] trait: * [`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 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] @@ -150,6 +153,10 @@ The conversions supported cover the following cases. [leu64-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/types/extra/trait.LeEqU64.html [leu8-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/types/extra/trait.LeEqU8.html [tf-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/traits/trait.Fixed.html +[tf-gs-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/traits/trait.Fixed.html#method.get_signed +[tf-gsm-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/traits/trait.Fixed.html#method.get_signed_mut +[tf-gu-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/traits/trait.Fixed.html#method.get_unsigned +[tf-gum-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/traits/trait.Fixed.html#method.get_unsigned_mut [tf-s-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/traits/trait.Fixed.html#associatedtype.Signed [tf-u-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/traits/trait.Fixed.html#associatedtype.Unsigned [tfs-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/traits/trait.FixedSigned.html diff --git a/RELEASES.md b/RELEASES.md index 5ced4bc..6c0a8b0 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -23,8 +23,11 @@ Version 1.9.0 (unreleased) [`overflowing_distance`][f-od-1-9] * The [`unsigned_distance`][f-unsd-1-9] method was added to all signed fixed-point types and to the [`FixedSigned`][tfs-1-9] trait. - * The following associated types were added to the [`Fixed`][tf-1-9] trait: + * The following associated types and provided methods were added to the + [`Fixed`][tf-1-9] trait: * [`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 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] @@ -66,6 +69,10 @@ Compatibility notes [leu64-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/types/extra/trait.LeEqU64.html [leu8-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/types/extra/trait.LeEqU8.html [tf-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/traits/trait.Fixed.html +[tf-gs-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/traits/trait.Fixed.html#method.get_signed +[tf-gsm-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/traits/trait.Fixed.html#method.get_signed_mut +[tf-gu-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/traits/trait.Fixed.html#method.get_unsigned +[tf-gum-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/traits/trait.Fixed.html#method.get_unsigned_mut [tf-s-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/traits/trait.Fixed.html#associatedtype.Signed [tf-u-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/traits/trait.Fixed.html#associatedtype.Unsigned [tfs-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/traits/trait.FixedSigned.html diff --git a/etc/gitlab-ci.yml b/etc/gitlab-ci.yml index 7e6f331..651b540 100644 --- a/etc/gitlab-ci.yml +++ b/etc/gitlab-ci.yml @@ -95,7 +95,7 @@ x86_64-gnulinux-tarpaulin: image: amd64/rust:1 variables: TARGET: x86_64 - REQ_COVERAGE: "78.9" + REQ_COVERAGE: "78.5" cache: key: $CI_JOB_NAME paths: diff --git a/src/traits.rs b/src/traits.rs index a5b34e3..26fd7c0 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -23,7 +23,7 @@ use crate::{ F128Bits, FixedI128, FixedI16, FixedI32, FixedI64, FixedI8, FixedU128, FixedU16, FixedU32, FixedU64, FixedU8, ParseFixedError, }; -use bytemuck::{Pod, TransparentWrapper}; +use bytemuck::{self, Pod, TransparentWrapper}; use core::{ fmt::{Binary, Debug, Display, LowerHex, Octal, UpperHex}, hash::Hash, @@ -398,6 +398,120 @@ where /// [types]: crate::types type Unsigned: FixedUnsigned; + /// Returns a reference to `self` if it is signed, or [`None`] if it is unsigned. + /// + /// # Examples + /// + /// ```rust + /// use fixed::{ + /// traits::Fixed, + /// types::{I16F16, U16F16}, + /// }; + /// + /// let i = I16F16::from_num(-3.5); + /// match i.get_signed() { + /// Some(signed) => assert_eq!(signed.signum(), -1), + /// None => unreachable!(), + /// } + /// + /// let u = U16F16::from_num(3.5); + /// assert!(u.get_signed().is_none()); + /// ``` + #[inline] + fn get_signed(&self) -> Option<&Self::Signed> { + if Self::IS_SIGNED { + Some(bytemuck::cast_ref(self)) + } else { + None + } + } + + /// Returns a reference to `self` if it is unsigned, or [`None`] if it is signed. + /// + /// # Examples + /// + /// ```rust + /// use fixed::{ + /// traits::Fixed, + /// types::{I16F16, U16F16}, + /// }; + /// + /// let u = U16F16::from_num(3.5); + /// match u.get_unsigned() { + /// Some(unsigned) => assert_eq!(unsigned.next_power_of_two(), 4), + /// None => unreachable!(), + /// } + /// + /// let i = I16F16::from_num(3.5); + /// assert!(i.get_unsigned().is_none()); + /// ``` + #[inline] + fn get_unsigned(&self) -> Option<&Self::Unsigned> { + if Self::IS_SIGNED { + None + } else { + Some(bytemuck::cast_ref(self)) + } + } + + /// Returns a mutable reference to `self` if it is signed, or [`None`] if it is unsigned. + /// + /// # Examples + /// + /// ```rust + /// use fixed::{ + /// traits::Fixed, + /// types::{I16F16, U16F16}, + /// }; + /// + /// let mut i = I16F16::from_num(-3.5); + /// match i.get_signed_mut() { + /// Some(signed) => *signed = signed.signum(), + /// None => unreachable!(), + /// } + /// assert_eq!(i, -1); + /// + /// let mut u = U16F16::from_num(3.5); + /// assert!(u.get_signed_mut().is_none()); + /// ``` + #[inline] + fn get_signed_mut(&mut self) -> Option<&mut Self::Signed> { + if Self::IS_SIGNED { + Some(bytemuck::cast_mut(self)) + } else { + None + } + } + + /// Returns a mutable reference to `self` if it is unsigned, or [`None`] if it is signed. + /// + /// # Examples + /// + /// ```rust + /// use fixed::{ + /// traits::Fixed, + /// types::{I16F16, U16F16}, + /// }; + /// + /// let mut u = U16F16::from_num(3.5); + /// match u.get_unsigned_mut() { + /// Some(unsigned) => *unsigned = unsigned.next_power_of_two(), + /// None => unreachable!(), + /// } + /// assert_eq!(u, 4); + /// + /// let mut i = I16F16::from_num(3.5); + /// assert!(i.get_unsigned_mut().is_none()); + /// ``` + #[inline] + fn get_unsigned_mut(&mut self) -> Option<&mut Self::Unsigned> { + if Self::IS_SIGNED { + None + } else { + Some(bytemuck::cast_mut(self)) + } + } + /// Zero. /// /// See also FixedI32::[ZERO][FixedI32::ZERO] and