mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer-rs.git
synced 2024-12-28 02:50:32 +00:00
gst/Signed: impl div & mul
This commit is contained in:
parent
1411c9e35e
commit
2b4fcb131e
3 changed files with 330 additions and 6 deletions
|
@ -225,6 +225,7 @@ impl From<ClockTime> for Duration {
|
|||
}
|
||||
|
||||
impl_common_ops_for_newtype_uint!(ClockTime, u64);
|
||||
impl_signed_div_mul!(ClockTime, u64);
|
||||
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// Tell [`pad_clocktime`] what kind of time we're formatting
|
||||
|
@ -492,7 +493,30 @@ mod tests {
|
|||
assert_eq!(P_CT_2 - N_CT_1, P_CT_3);
|
||||
assert_eq!(N_CT_2 - P_CT_1, N_CT_3);
|
||||
assert_eq!(N_CT_3 - N_CT_1, N_CT_2);
|
||||
assert_eq!(N_CT_2 - N_CT_3, P_CT_1);
|
||||
|
||||
assert_eq!(P_CT_1 * 2i64, P_CT_2);
|
||||
assert_eq!(P_CT_1 * -2i64, N_CT_2);
|
||||
assert_eq!(N_CT_1 * 2i64, N_CT_2);
|
||||
assert_eq!(N_CT_1 * -2i64, P_CT_2);
|
||||
|
||||
assert_eq!(P_CT_1 * 2u64, P_CT_2);
|
||||
assert_eq!(N_CT_1 * 2u64, N_CT_2);
|
||||
|
||||
assert_eq!(P_CT_2 / 2i64, P_CT_1);
|
||||
assert_eq!(P_CT_2 / -2i64, N_CT_1);
|
||||
assert_eq!(N_CT_2 / 2i64, N_CT_1);
|
||||
assert_eq!(N_CT_2 / -2i64, P_CT_1);
|
||||
|
||||
assert_eq!(P_CT_2 / 2u64, P_CT_1);
|
||||
assert_eq!(N_CT_2 / 2u64, N_CT_1);
|
||||
|
||||
assert_eq!(P_CT_3 % 2i64, P_CT_1);
|
||||
assert_eq!(P_CT_3 % -2i64, P_CT_1);
|
||||
assert_eq!(N_CT_3 % 2i64, N_CT_1);
|
||||
assert_eq!(N_CT_3 % -2i64, N_CT_1);
|
||||
|
||||
assert_eq!(P_CT_3 % 2u64, P_CT_1);
|
||||
assert_eq!(N_CT_3 % 2u64, N_CT_1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -537,6 +561,24 @@ mod tests {
|
|||
Some(CT_1).opt_checked_sub(CT_2),
|
||||
Err(opt_ops::Error::Overflow)
|
||||
);
|
||||
|
||||
assert_eq!(CT_1.checked_mul(2), Some(CT_2));
|
||||
assert_eq!(P_CT_1.checked_mul(2), Some(P_CT_2));
|
||||
assert_eq!(P_CT_1.checked_mul(-2), Some(N_CT_2));
|
||||
assert_eq!(N_CT_1.checked_mul(2), Some(N_CT_2));
|
||||
assert_eq!(N_CT_1.checked_mul(-2), Some(P_CT_2));
|
||||
|
||||
assert_eq!(P_CT_1.checked_mul_unsigned(2u64), Some(P_CT_2));
|
||||
assert_eq!(N_CT_1.checked_mul_unsigned(2u64), Some(N_CT_2));
|
||||
|
||||
assert_eq!(CT_3.checked_div(3), Some(CT_1));
|
||||
assert_eq!(P_CT_3.checked_div(3), Some(P_CT_1));
|
||||
assert_eq!(P_CT_3.checked_div(-3), Some(N_CT_1));
|
||||
assert_eq!(N_CT_3.checked_div(3), Some(N_CT_1));
|
||||
assert_eq!(N_CT_3.checked_div(-3), Some(P_CT_1));
|
||||
|
||||
assert_eq!(P_CT_3.checked_div_unsigned(3u64), Some(P_CT_1));
|
||||
assert_eq!(N_CT_3.checked_div_unsigned(3u64), Some(N_CT_1));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -584,6 +626,7 @@ mod tests {
|
|||
#[test]
|
||||
fn saturating_ops() {
|
||||
let p_ct_max: Signed<ClockTime> = ClockTime::MAX.into_positive();
|
||||
let n_ct_max: Signed<ClockTime> = ClockTime::MAX.into_negative();
|
||||
|
||||
assert_eq!(CT_1.saturating_add(CT_2), CT_3);
|
||||
assert_eq!(P_CT_1.saturating_add(P_CT_2), P_CT_3);
|
||||
|
@ -625,6 +668,20 @@ mod tests {
|
|||
|
||||
assert_eq!(CT_1.saturating_mul(2), CT_2);
|
||||
assert_eq!(ClockTime::MAX.saturating_mul(2), ClockTime::MAX);
|
||||
|
||||
assert_eq!(P_CT_1.saturating_mul(2), P_CT_2);
|
||||
assert_eq!(P_CT_1.saturating_mul(-2), N_CT_2);
|
||||
assert_eq!(N_CT_1.saturating_mul(2), N_CT_2);
|
||||
assert_eq!(N_CT_1.saturating_mul(-2), P_CT_2);
|
||||
|
||||
assert_eq!(P_CT_1.saturating_mul_unsigned(2u64), P_CT_2);
|
||||
assert_eq!(N_CT_1.saturating_mul_unsigned(2u64), N_CT_2);
|
||||
|
||||
assert_eq!(p_ct_max.saturating_mul(2), p_ct_max);
|
||||
assert_eq!(n_ct_max.saturating_mul(2), n_ct_max);
|
||||
|
||||
assert_eq!(p_ct_max.saturating_mul_unsigned(2u64), p_ct_max);
|
||||
assert_eq!(n_ct_max.saturating_mul_unsigned(2u64), n_ct_max);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -235,13 +235,16 @@ pub trait UnsignedIntoSigned: Copy + Sized {
|
|||
}
|
||||
|
||||
impl_unsigned_int_into_signed!(u64);
|
||||
impl_signed_ops!(u64, 0);
|
||||
impl_signed_ops!(u64);
|
||||
impl_signed_div_mul!(u64);
|
||||
|
||||
impl_unsigned_int_into_signed!(usize);
|
||||
impl_signed_ops!(usize, 0);
|
||||
impl_signed_ops!(usize);
|
||||
impl_signed_div_mul!(usize);
|
||||
|
||||
impl_unsigned_int_into_signed!(u32);
|
||||
impl_signed_ops!(u32, 0);
|
||||
impl_signed_ops!(u32);
|
||||
impl_signed_div_mul!(u32);
|
||||
|
||||
impl From<i64> for Signed<u64> {
|
||||
fn from(val: i64) -> Signed<u64> {
|
||||
|
@ -796,6 +799,7 @@ impl UnsignedIntoSigned for GenericFormattedValue {
|
|||
}
|
||||
|
||||
impl_common_ops_for_newtype_uint!(Default, u64);
|
||||
impl_signed_div_mul!(Default, u64);
|
||||
impl_format_value_traits!(Default, Default, Default, u64);
|
||||
option_glib_newtype_from_to!(Default, u64::MAX);
|
||||
glib_newtype_display!(
|
||||
|
@ -806,6 +810,7 @@ glib_newtype_display!(
|
|||
);
|
||||
|
||||
impl_common_ops_for_newtype_uint!(Bytes, u64);
|
||||
impl_signed_div_mul!(Bytes, u64);
|
||||
impl_format_value_traits!(Bytes, Bytes, Bytes, u64);
|
||||
option_glib_newtype_from_to!(Bytes, u64::MAX);
|
||||
glib_newtype_display!(Bytes, DisplayableBytes, DisplayableOptionBytes, "bytes");
|
||||
|
@ -813,6 +818,7 @@ glib_newtype_display!(Bytes, DisplayableBytes, DisplayableOptionBytes, "bytes");
|
|||
impl_format_value_traits!(ClockTime, Time, Time, u64);
|
||||
|
||||
impl_common_ops_for_newtype_uint!(Buffers, u64);
|
||||
impl_signed_div_mul!(Buffers, u64);
|
||||
impl_format_value_traits!(Buffers, Buffers, Buffers, u64);
|
||||
option_glib_newtype_from_to!(Buffers, Buffers::OFFSET_NONE);
|
||||
glib_newtype_display!(
|
||||
|
@ -919,6 +925,7 @@ impl From<Undefined> for Signed<u64> {
|
|||
glib_newtype_display!(Undefined, DisplayableUndefined, "(Undefined)");
|
||||
|
||||
impl_common_ops_for_newtype_uint!(Percent, u32);
|
||||
impl_signed_div_mul!(Percent, u32);
|
||||
glib_newtype_display!(Percent, DisplayablePercent, DisplayableOptionPercent, "%");
|
||||
|
||||
impl FormattedValue for Option<Percent> {
|
||||
|
|
|
@ -158,6 +158,12 @@ macro_rules! impl_non_trait_op_inner_type(
|
|||
}
|
||||
}
|
||||
|
||||
#[must_use = "this returns the result of the operation, without modifying the original"]
|
||||
#[inline]
|
||||
pub const fn saturating_div(self, rhs: $inner_type) -> Self {
|
||||
Self(self.0.saturating_div(rhs))
|
||||
}
|
||||
|
||||
#[must_use = "this returns the result of the operation, without modifying the original"]
|
||||
#[inline]
|
||||
pub const fn checked_mul(self, rhs: $inner_type) -> Option<Self> {
|
||||
|
@ -266,7 +272,7 @@ macro_rules! impl_common_ops_for_newtype_uint(
|
|||
impl_non_trait_op_inner_type!($name, $inner_type);
|
||||
|
||||
impl_unsigned_int_into_signed!($name);
|
||||
impl_signed_ops!($name, $name::ZERO);
|
||||
impl_signed_ops!($name, $inner_type, $name::ZERO);
|
||||
|
||||
impl<ND: Borrow<$inner_type>> MulDiv<ND> for $name {
|
||||
type Output = $name;
|
||||
|
@ -423,7 +429,19 @@ macro_rules! impl_common_ops_for_newtype_uint(
|
|||
);
|
||||
|
||||
macro_rules! impl_signed_ops(
|
||||
($type:ty, $zero:expr) => {
|
||||
(u64) => {
|
||||
impl_signed_ops!(u64, u64, 0);
|
||||
};
|
||||
|
||||
(usize) => {
|
||||
impl_signed_ops!(usize, usize, 0);
|
||||
};
|
||||
|
||||
(u32) => {
|
||||
impl_signed_ops!(u32, u32, 0);
|
||||
};
|
||||
|
||||
($type:ty, $inner_type:ty, $zero:expr) => {
|
||||
impl crate::Signed<$type> {
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// Returns the signum for this `Signed`.
|
||||
|
@ -615,6 +633,248 @@ macro_rules! impl_signed_ops(
|
|||
};
|
||||
);
|
||||
|
||||
macro_rules! impl_signed_div_mul(
|
||||
(u64) => {
|
||||
impl_signed_div_mul!(u64, u64, i64);
|
||||
};
|
||||
|
||||
(usize) => {
|
||||
impl_signed_div_mul!(usize, usize, isize);
|
||||
};
|
||||
|
||||
(u32) => {
|
||||
impl_signed_div_mul!(u32, u32, i32);
|
||||
};
|
||||
|
||||
($type:ty, u64) => {
|
||||
impl_signed_div_mul!($type, u64, i64);
|
||||
};
|
||||
|
||||
($type:ty, usize) => {
|
||||
impl_signed_div_mul!($type, usize, isize);
|
||||
};
|
||||
|
||||
($type:ty, u32) => {
|
||||
impl_signed_div_mul!($type, u32, i32);
|
||||
};
|
||||
|
||||
($type:ty, $inner_type:ty, $signed_rhs:ty) => {
|
||||
impl crate::Signed<$type> {
|
||||
#[must_use = "this returns the result of the operation, without modifying the original"]
|
||||
pub fn checked_div(self, rhs:$signed_rhs) -> Option<Self> {
|
||||
use crate::UnsignedIntoSigned;
|
||||
use crate::Signed::*;
|
||||
match self {
|
||||
Positive(lhs) => {
|
||||
if rhs.is_positive() {
|
||||
lhs.checked_div(rhs as $inner_type).map(<$type>::into_positive)
|
||||
} else {
|
||||
lhs.checked_div(-rhs as $inner_type).map(<$type>::into_negative)
|
||||
}
|
||||
}
|
||||
Negative(lhs) => {
|
||||
if rhs.is_positive() {
|
||||
lhs.checked_div(rhs as $inner_type).map(<$type>::into_negative)
|
||||
} else {
|
||||
lhs.checked_div(-rhs as $inner_type).map(<$type>::into_positive)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use = "this returns the result of the operation, without modifying the original"]
|
||||
pub fn checked_div_unsigned(self, rhs:$inner_type) -> Option<Self> {
|
||||
use crate::UnsignedIntoSigned;
|
||||
use crate::Signed::*;
|
||||
match self {
|
||||
Positive(lhs) => lhs.checked_div(rhs).map(<$type>::into_positive),
|
||||
Negative(lhs) => lhs.checked_div(rhs).map(<$type>::into_negative),
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use = "this returns the result of the operation, without modifying the original"]
|
||||
pub fn checked_rem(self, rhs:$signed_rhs) -> Option<Self> {
|
||||
use crate::UnsignedIntoSigned;
|
||||
use crate::Signed::*;
|
||||
match self {
|
||||
Positive(lhs) => {
|
||||
if rhs.is_positive() {
|
||||
lhs.checked_rem(rhs as $inner_type).map(<$type>::into_positive)
|
||||
} else {
|
||||
lhs.checked_rem(-rhs as $inner_type).map(<$type>::into_positive)
|
||||
}
|
||||
}
|
||||
Negative(lhs) => {
|
||||
if rhs.is_positive() {
|
||||
lhs.checked_rem(rhs as $inner_type).map(<$type>::into_negative)
|
||||
} else {
|
||||
lhs.checked_rem(-rhs as $inner_type).map(<$type>::into_negative)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use = "this returns the result of the operation, without modifying the original"]
|
||||
pub fn checked_rem_unsigned(self, rhs:$inner_type) -> Option<Self> {
|
||||
use crate::UnsignedIntoSigned;
|
||||
use crate::Signed::*;
|
||||
match self {
|
||||
Positive(lhs) => lhs.checked_rem(rhs).map(<$type>::into_positive),
|
||||
Negative(lhs) => lhs.checked_rem(rhs).map(<$type>::into_negative),
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use = "this returns the result of the operation, without modifying the original"]
|
||||
pub fn checked_mul(self, rhs:$signed_rhs) -> Option<Self> {
|
||||
use crate::UnsignedIntoSigned;
|
||||
use crate::Signed::*;
|
||||
match self {
|
||||
Positive(lhs) => {
|
||||
if rhs.is_positive() {
|
||||
lhs.checked_mul(rhs as $inner_type).map(<$type>::into_positive)
|
||||
} else {
|
||||
lhs.checked_mul(-rhs as $inner_type).map(<$type>::into_negative)
|
||||
}
|
||||
}
|
||||
Negative(lhs) => {
|
||||
if rhs.is_positive() {
|
||||
lhs.checked_mul(rhs as $inner_type).map(<$type>::into_negative)
|
||||
} else {
|
||||
lhs.checked_mul(-rhs as $inner_type).map(<$type>::into_positive)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use = "this returns the result of the operation, without modifying the original"]
|
||||
pub fn checked_mul_unsigned(self, rhs:$inner_type) -> Option<Self> {
|
||||
use crate::UnsignedIntoSigned;
|
||||
use crate::Signed::*;
|
||||
match self {
|
||||
Positive(lhs) => lhs.checked_mul(rhs).map(<$type>::into_positive),
|
||||
Negative(lhs) => lhs.checked_mul(rhs).map(<$type>::into_negative),
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use = "this returns the result of the operation, without modifying the original"]
|
||||
pub fn saturating_mul(self, rhs:$signed_rhs) -> Self {
|
||||
use crate::UnsignedIntoSigned;
|
||||
use crate::Signed::*;
|
||||
match self {
|
||||
Positive(lhs) => {
|
||||
if rhs.is_positive() {
|
||||
lhs.saturating_mul(rhs as $inner_type).into_positive()
|
||||
} else {
|
||||
lhs.saturating_mul(-rhs as $inner_type).into_negative()
|
||||
}
|
||||
}
|
||||
Negative(lhs) => {
|
||||
if rhs.is_positive() {
|
||||
lhs.saturating_mul(rhs as $inner_type).into_negative()
|
||||
} else {
|
||||
lhs.saturating_mul(-rhs as $inner_type).into_positive()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use = "this returns the result of the operation, without modifying the original"]
|
||||
pub fn saturating_mul_unsigned(self, rhs:$inner_type) -> Self {
|
||||
use crate::UnsignedIntoSigned;
|
||||
use crate::Signed::*;
|
||||
match self {
|
||||
Positive(lhs) => lhs.saturating_mul(rhs).into_positive(),
|
||||
Negative(lhs) => lhs.saturating_mul(rhs).into_negative(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Div<$signed_rhs> for crate::Signed<$type> {
|
||||
type Output = crate::Signed<$type>;
|
||||
|
||||
fn div(self, rhs: $signed_rhs) -> crate::Signed<$type> {
|
||||
self.checked_div(rhs).expect("division overflowed")
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::DivAssign<$signed_rhs> for crate::Signed<$type> {
|
||||
fn div_assign(&mut self, rhs: $signed_rhs) {
|
||||
*self = std::ops::Div::div(*self, rhs);
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Div<$inner_type> for crate::Signed<$type> {
|
||||
type Output = crate::Signed<$type>;
|
||||
|
||||
fn div(self, rhs: $inner_type) -> crate::Signed<$type> {
|
||||
self.checked_div_unsigned(rhs).expect("division overflowed")
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::DivAssign<$inner_type> for crate::Signed<$type> {
|
||||
fn div_assign(&mut self, rhs: $inner_type) {
|
||||
*self = std::ops::Div::div(*self, rhs);
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Rem<$signed_rhs> for crate::Signed<$type> {
|
||||
type Output = crate::Signed<$type>;
|
||||
|
||||
fn rem(self, rhs: $signed_rhs) -> crate::Signed<$type> {
|
||||
self.checked_rem(rhs).expect("division overflowed")
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::RemAssign<$signed_rhs> for crate::Signed<$type> {
|
||||
fn rem_assign(&mut self, rhs: $signed_rhs) {
|
||||
*self = std::ops::Rem::rem(*self, rhs);
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Rem<$inner_type> for crate::Signed<$type> {
|
||||
type Output = crate::Signed<$type>;
|
||||
|
||||
fn rem(self, rhs: $inner_type) -> crate::Signed<$type> {
|
||||
self.checked_rem_unsigned(rhs).expect("division overflowed")
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::RemAssign<$inner_type> for crate::Signed<$type> {
|
||||
fn rem_assign(&mut self, rhs: $inner_type) {
|
||||
*self = std::ops::Rem::rem(*self, rhs);
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Mul<$signed_rhs> for crate::Signed<$type> {
|
||||
type Output = crate::Signed<$type>;
|
||||
|
||||
fn mul(self, rhs: $signed_rhs) -> crate::Signed<$type> {
|
||||
self.checked_mul(rhs).expect("multiplication overflowed")
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::MulAssign<$signed_rhs> for crate::Signed<$type> {
|
||||
fn mul_assign(&mut self, rhs: $signed_rhs) {
|
||||
*self = std::ops::Mul::mul(*self, rhs);
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Mul<$inner_type> for crate::Signed<$type> {
|
||||
type Output = crate::Signed<$type>;
|
||||
|
||||
fn mul(self, rhs: $inner_type) -> crate::Signed<$type> {
|
||||
self.checked_mul_unsigned(rhs).expect("multiplication overflowed")
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::MulAssign<$inner_type> for crate::Signed<$type> {
|
||||
fn mul_assign(&mut self, rhs: $inner_type) {
|
||||
*self = std::ops::Mul::mul(*self, rhs);
|
||||
}
|
||||
}
|
||||
};
|
||||
);
|
||||
|
||||
macro_rules! impl_format_value_traits(
|
||||
($name:ident, $format:ident, $format_value:ident, $inner_type:ty) => {
|
||||
impl FormattedValue for Option<$name> {
|
||||
|
|
Loading…
Reference in a new issue