forked from mirrors/gstreamer-rs
gst/Signed: impl MulDiv
This commit is contained in:
parent
2b4fcb131e
commit
183a399d1d
3 changed files with 199 additions and 12 deletions
|
@ -711,6 +711,48 @@ mod tests {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mul_div_ops() {
|
||||
assert_eq!(CT_1.mul_div_floor(7, 3), Some(CT_2));
|
||||
|
||||
assert_eq!(P_CT_1.mul_div_floor(7u64, 3), Some(P_CT_2));
|
||||
assert_eq!(P_CT_1.mul_div_floor(-7i64, 3), Some(N_CT_2));
|
||||
assert_eq!(P_CT_1.mul_div_floor(7i64, -3), Some(N_CT_2));
|
||||
assert_eq!(P_CT_1.mul_div_floor(-7i64, -3), Some(P_CT_2));
|
||||
|
||||
assert_eq!(N_CT_1.mul_div_floor(7u64, 3), Some(N_CT_2));
|
||||
assert_eq!(N_CT_1.mul_div_floor(-7i64, 3), Some(P_CT_2));
|
||||
assert_eq!(N_CT_1.mul_div_floor(7i64, -3), Some(P_CT_2));
|
||||
assert_eq!(N_CT_1.mul_div_floor(-7i64, -3), Some(N_CT_2));
|
||||
|
||||
assert_eq!(CT_1.mul_div_round(10, 3), Some(CT_3));
|
||||
assert_eq!(CT_1.mul_div_round(8, 3), Some(CT_3));
|
||||
|
||||
assert_eq!(P_CT_1.mul_div_round(10u64, 3), Some(P_CT_3));
|
||||
assert_eq!(P_CT_1.mul_div_round(8u64, 3), Some(P_CT_3));
|
||||
assert_eq!(P_CT_1.mul_div_round(-10i64, 3), Some(N_CT_3));
|
||||
assert_eq!(P_CT_1.mul_div_round(-8i64, 3), Some(N_CT_3));
|
||||
assert_eq!(P_CT_1.mul_div_round(10i64, -3), Some(N_CT_3));
|
||||
assert_eq!(P_CT_1.mul_div_round(-10i64, -3), Some(P_CT_3));
|
||||
|
||||
assert_eq!(N_CT_1.mul_div_round(10u64, 3), Some(N_CT_3));
|
||||
assert_eq!(N_CT_1.mul_div_round(-10i64, 3), Some(P_CT_3));
|
||||
assert_eq!(N_CT_1.mul_div_round(10i64, -3), Some(P_CT_3));
|
||||
assert_eq!(N_CT_1.mul_div_round(-10i64, -3), Some(N_CT_3));
|
||||
|
||||
assert_eq!(CT_1.mul_div_ceil(7, 3), Some(CT_3));
|
||||
|
||||
assert_eq!(P_CT_1.mul_div_ceil(7u64, 3), Some(P_CT_3));
|
||||
assert_eq!(P_CT_1.mul_div_ceil(-7i64, 3), Some(N_CT_3));
|
||||
assert_eq!(P_CT_1.mul_div_ceil(7i64, -3), Some(N_CT_3));
|
||||
assert_eq!(P_CT_1.mul_div_ceil(-7i64, -3), Some(P_CT_3));
|
||||
|
||||
assert_eq!(N_CT_1.mul_div_ceil(7u64, 3), Some(N_CT_3));
|
||||
assert_eq!(N_CT_1.mul_div_ceil(-7i64, 3), Some(P_CT_3));
|
||||
assert_eq!(N_CT_1.mul_div_ceil(7i64, -3), Some(P_CT_3));
|
||||
assert_eq!(N_CT_1.mul_div_ceil(-7i64, -3), Some(N_CT_3));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[allow(clippy::nonminimal_bool)]
|
||||
fn comp() {
|
||||
|
|
|
@ -1003,6 +1003,19 @@ impl TryFromGlib<i64> for Percent {
|
|||
}
|
||||
}
|
||||
|
||||
impl TryFrom<u32> for Percent {
|
||||
type Error = FormattedValueError;
|
||||
|
||||
fn try_from(value: u32) -> Result<Self, Self::Error> {
|
||||
skip_assert_initialized!();
|
||||
if value > ffi::GST_FORMAT_PERCENT_MAX as u32 {
|
||||
Err(FormattedValueError(Format::Percent))
|
||||
} else {
|
||||
Ok(Percent(value))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<GenericFormattedValue> for Option<Percent> {
|
||||
type Error = FormattedValueError;
|
||||
|
||||
|
|
|
@ -635,30 +635,31 @@ macro_rules! impl_signed_ops(
|
|||
|
||||
macro_rules! impl_signed_div_mul(
|
||||
(u64) => {
|
||||
impl_signed_div_mul!(u64, u64, i64);
|
||||
impl_signed_div_mul!(u64, u64, i64, |val: u64| val);
|
||||
impl_signed_div_mul_trait!(u64, u64, i64, |val: u64| val);
|
||||
};
|
||||
|
||||
(usize) => {
|
||||
impl_signed_div_mul!(usize, usize, isize);
|
||||
impl_signed_div_mul!(usize, usize, isize, |val: usize| val);
|
||||
// `MulDiv` not available for usize
|
||||
};
|
||||
|
||||
(u32) => {
|
||||
impl_signed_div_mul!(u32, u32, i32);
|
||||
impl_signed_div_mul!(u32, u32, i32, |val: u32| val);
|
||||
impl_signed_div_mul_trait!(u32, u32, i32, |val: u32| val);
|
||||
};
|
||||
|
||||
($type:ty, u64) => {
|
||||
impl_signed_div_mul!($type, u64, i64);
|
||||
($new_type:ty, u64) => {
|
||||
impl_signed_div_mul!($new_type, u64, i64, |val: $new_type| *val);
|
||||
impl_signed_div_mul_trait!($new_type, u64, i64, |val: $new_type| *val);
|
||||
};
|
||||
|
||||
($type:ty, usize) => {
|
||||
impl_signed_div_mul!($type, usize, isize);
|
||||
($new_type:ty, u32) => {
|
||||
impl_signed_div_mul!($new_type, u32, i32, |val: $new_type| *val);
|
||||
impl_signed_div_mul_trait!($new_type, u32, i32, |val: $new_type| *val);
|
||||
};
|
||||
|
||||
($type:ty, u32) => {
|
||||
impl_signed_div_mul!($type, u32, i32);
|
||||
};
|
||||
|
||||
($type:ty, $inner_type:ty, $signed_rhs:ty) => {
|
||||
($type:ty, $inner_type:ty, $signed_rhs:ty, $into_inner:expr) => {
|
||||
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> {
|
||||
|
@ -875,6 +876,137 @@ macro_rules! impl_signed_div_mul(
|
|||
};
|
||||
);
|
||||
|
||||
macro_rules! impl_signed_div_mul_trait(
|
||||
($type:ty, $inner_type:ty, $signed_rhs:ty, $into_inner:expr) => {
|
||||
impl crate::Signed<$type> {
|
||||
fn signed_from_inner(val: $inner_type, sign: $signed_rhs) -> Option<crate::Signed<$type>> {
|
||||
skip_assert_initialized!();
|
||||
if sign.is_positive() {
|
||||
Self::positive_from_inner(val)
|
||||
} else {
|
||||
Self::negative_from_inner(val)
|
||||
}
|
||||
}
|
||||
|
||||
fn positive_from_inner(val: $inner_type) -> Option<crate::Signed<$type>> {
|
||||
skip_assert_initialized!();
|
||||
use crate::UnsignedIntoSigned;
|
||||
<$type>::try_from(val).ok().map(<$type>::into_positive)
|
||||
}
|
||||
|
||||
fn negative_from_inner(val: $inner_type) -> Option<crate::Signed<$type>> {
|
||||
skip_assert_initialized!();
|
||||
use crate::UnsignedIntoSigned;
|
||||
<$type>::try_from(val).ok().map(<$type>::into_negative)
|
||||
}
|
||||
}
|
||||
|
||||
impl MulDiv<$signed_rhs> for crate::Signed<$type> {
|
||||
type Output = crate::Signed<$type>;
|
||||
|
||||
fn mul_div_floor(self, num: $signed_rhs, denom: $signed_rhs) -> Option<Self::Output> {
|
||||
use crate::Signed::*;
|
||||
match self {
|
||||
Positive(lhs) => {
|
||||
$into_inner(lhs)
|
||||
.mul_div_floor(num.abs() as $inner_type, denom.abs() as $inner_type)
|
||||
.and_then(|val| Self::signed_from_inner(val, num.signum() * denom.signum()))
|
||||
}
|
||||
Negative(lhs) => {
|
||||
$into_inner(lhs)
|
||||
.mul_div_floor(num.abs() as $inner_type, denom.abs() as $inner_type)
|
||||
.and_then(|val| Self::signed_from_inner(val, -num.signum() * denom.signum()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn mul_div_round(self, num: $signed_rhs, denom: $signed_rhs) -> Option<Self::Output> {
|
||||
use crate::Signed::*;
|
||||
match self {
|
||||
Positive(lhs) => {
|
||||
$into_inner(lhs)
|
||||
.mul_div_round(num.abs() as $inner_type, denom.abs() as $inner_type)
|
||||
.and_then(|val| Self::signed_from_inner(val, num.signum() * denom.signum()))
|
||||
}
|
||||
Negative(lhs) => {
|
||||
$into_inner(lhs)
|
||||
.mul_div_round(num.abs() as $inner_type, denom.abs() as $inner_type)
|
||||
.and_then(|val| Self::signed_from_inner(val, -num.signum() * denom.signum()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn mul_div_ceil(self, num: $signed_rhs, denom: $signed_rhs) -> Option<Self::Output> {
|
||||
use crate::Signed::*;
|
||||
match self {
|
||||
Positive(lhs) => {
|
||||
$into_inner(lhs)
|
||||
.mul_div_ceil(num.abs() as $inner_type, denom.abs() as $inner_type)
|
||||
.and_then(|val| Self::signed_from_inner(val, num.signum() * denom.signum()))
|
||||
}
|
||||
Negative(lhs) => {
|
||||
$into_inner(lhs)
|
||||
.mul_div_ceil(num.abs() as $inner_type, denom.abs() as $inner_type)
|
||||
.and_then(|val| Self::signed_from_inner(val, -num.signum() * denom.signum()))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl MulDiv<$inner_type> for crate::Signed<$type> {
|
||||
type Output = crate::Signed<$type>;
|
||||
|
||||
fn mul_div_floor(self, num: $inner_type, denom: $inner_type) -> Option<Self::Output> {
|
||||
use crate::Signed::*;
|
||||
match self {
|
||||
Positive(lhs) => {
|
||||
$into_inner(lhs)
|
||||
.mul_div_floor(num, denom)
|
||||
.and_then(Self::positive_from_inner)
|
||||
}
|
||||
Negative(lhs) => {
|
||||
$into_inner(lhs)
|
||||
.mul_div_floor(num, denom)
|
||||
.and_then(Self::negative_from_inner)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn mul_div_round(self, num: $inner_type, denom: $inner_type) -> Option<Self::Output> {
|
||||
use crate::Signed::*;
|
||||
match self {
|
||||
Positive(lhs) => {
|
||||
$into_inner(lhs)
|
||||
.mul_div_round(num, denom)
|
||||
.and_then(Self::positive_from_inner)
|
||||
}
|
||||
Negative(lhs) => {
|
||||
$into_inner(lhs)
|
||||
.mul_div_round(num, denom)
|
||||
.and_then(Self::negative_from_inner)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn mul_div_ceil(self, num: $inner_type, denom: $inner_type) -> Option<Self::Output> {
|
||||
use crate::Signed::*;
|
||||
match self {
|
||||
Positive(lhs) => {
|
||||
$into_inner(lhs)
|
||||
.mul_div_ceil(num, denom)
|
||||
.and_then(Self::positive_from_inner)
|
||||
}
|
||||
Negative(lhs) => {
|
||||
$into_inner(lhs)
|
||||
.mul_div_ceil(num, denom)
|
||||
.and_then(Self::negative_from_inner)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
);
|
||||
|
||||
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