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]
|
#[test]
|
||||||
#[allow(clippy::nonminimal_bool)]
|
#[allow(clippy::nonminimal_bool)]
|
||||||
fn comp() {
|
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> {
|
impl TryFrom<GenericFormattedValue> for Option<Percent> {
|
||||||
type Error = FormattedValueError;
|
type Error = FormattedValueError;
|
||||||
|
|
||||||
|
|
|
@ -635,30 +635,31 @@ macro_rules! impl_signed_ops(
|
||||||
|
|
||||||
macro_rules! impl_signed_div_mul(
|
macro_rules! impl_signed_div_mul(
|
||||||
(u64) => {
|
(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) => {
|
(usize) => {
|
||||||
impl_signed_div_mul!(usize, usize, isize);
|
impl_signed_div_mul!(usize, usize, isize, |val: usize| val);
|
||||||
|
// `MulDiv` not available for usize
|
||||||
};
|
};
|
||||||
|
|
||||||
(u32) => {
|
(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) => {
|
($new_type:ty, u64) => {
|
||||||
impl_signed_div_mul!($type, u64, i64);
|
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) => {
|
($new_type:ty, u32) => {
|
||||||
impl_signed_div_mul!($type, usize, isize);
|
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) => {
|
($type:ty, $inner_type:ty, $signed_rhs:ty, $into_inner:expr) => {
|
||||||
impl_signed_div_mul!($type, u32, i32);
|
|
||||||
};
|
|
||||||
|
|
||||||
($type:ty, $inner_type:ty, $signed_rhs:ty) => {
|
|
||||||
impl crate::Signed<$type> {
|
impl crate::Signed<$type> {
|
||||||
#[must_use = "this returns the result of the operation, without modifying the original"]
|
#[must_use = "this returns the result of the operation, without modifying the original"]
|
||||||
pub fn checked_div(self, rhs:$signed_rhs) -> Option<Self> {
|
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(
|
macro_rules! impl_format_value_traits(
|
||||||
($name:ident, $format:ident, $format_value:ident, $inner_type:ty) => {
|
($name:ident, $format:ident, $format_value:ident, $inner_type:ty) => {
|
||||||
impl FormattedValue for Option<$name> {
|
impl FormattedValue for Option<$name> {
|
||||||
|
|
Loading…
Reference in a new issue