#[macro_use]
mod checked_int;
mod floats;
mod lattice;
mod order;
mod present;
pub mod zset;
pub use checked_int::CheckedInt;
pub use floats::{F32, F64};
pub use lattice::Lattice;
pub use order::{PartialOrder, TotalOrder};
pub use present::Present;
pub use zset::{
DynZWeight, IndexedZSet, IndexedZSetReader, OrdIndexedZSet, OrdIndexedZSetFactories, OrdZSet,
OrdZSetFactories, VecIndexedZSet, VecIndexedZSetFactories, VecZSet, VecZSetFactories, ZBatch,
ZBatchReader, ZCursor, ZSet, ZSetReader, ZTrace, ZWeight,
};
use num::PrimInt;
use rust_decimal::{prelude::One, prelude::Zero, Decimal};
use size_of::SizeOf;
use std::{
fmt::{Debug, Display},
marker::PhantomData,
num::Wrapping,
ops::{Add, AddAssign, Mul, Neg},
rc::Rc,
};
pub trait MinValue {
fn min_value() -> Self;
}
pub trait MaxValue {
fn max_value() -> Self;
}
pub trait FirstLargeValue {
fn large() -> Self;
}
pub trait UnsignedPrimInt: PrimInt + FirstLargeValue + HasZero + Debug + Display {}
impl FirstLargeValue for u8 {
fn large() -> Self {
0x1
}
}
impl FirstLargeValue for u16 {
fn large() -> Self {
0x100
}
}
impl FirstLargeValue for u32 {
fn large() -> Self {
0x10000
}
}
impl FirstLargeValue for u64 {
fn large() -> Self {
0x1_0000_0000
}
}
impl FirstLargeValue for u128 {
fn large() -> Self {
0x1_0000_0000_0000_0000
}
}
impl UnsignedPrimInt for u8 {}
impl UnsignedPrimInt for u16 {}
impl UnsignedPrimInt for u32 {}
impl UnsignedPrimInt for u64 {}
impl UnsignedPrimInt for u128 {}
pub trait SignedPrimInt:
PrimInt + Neg<Output = Self> + HasZero + HasOne + Ord + Debug + Display
{
}
macro_rules! make_signed {
($type: ty) => {
impl MinValue for $type {
fn min_value() -> Self {
<$type>::MIN
}
}
impl MaxValue for $type {
fn max_value() -> Self {
<$type>::MAX
}
}
impl SignedPrimInt for $type {}
};
}
make_signed!(i8);
make_signed!(i16);
make_signed!(i32);
make_signed!(i64);
make_signed!(i128);
pub trait HasZero {
fn is_zero(&self) -> bool;
fn zero() -> Self;
}
macro_rules! impl_has_zero {
($($type:ty),* $(,)?) => {
$(
impl $crate::algebra::HasZero for $type {
#[inline]
fn is_zero(&self) -> bool {
*self == 0
}
#[inline]
fn zero() -> Self {
0
}
}
)*
};
}
impl_has_zero! {
u8,
i8,
u16,
i16,
u32,
i32,
u64,
i64,
u128,
i128,
usize,
isize,
}
impl HasZero for Decimal {
#[inline]
fn is_zero(&self) -> bool {
Zero::is_zero(self)
}
#[inline]
fn zero() -> Self {
Zero::zero()
}
}
impl<T> HasZero for Option<T> {
#[inline]
fn is_zero(&self) -> bool {
self.is_none()
}
#[inline]
fn zero() -> Self {
None
}
}
impl<T> HasZero for Wrapping<T>
where
T: HasZero,
{
#[inline]
fn is_zero(&self) -> bool {
self.0.is_zero()
}
#[inline]
fn zero() -> Self {
Self(T::zero())
}
}
pub trait HasOne {
fn one() -> Self;
}
macro_rules! impl_has_one {
($($type:ty),* $(,)?) => {
$(
impl $crate::algebra::HasOne for $type {
#[inline]
fn one() -> Self {
1
}
}
)*
};
}
impl HasOne for Decimal {
#[inline]
fn one() -> Self {
One::one()
}
}
impl_has_one! {
u8,
i8,
u16,
i16,
u32,
i32,
u64,
i64,
u128,
i128,
usize,
isize,
}
impl<T> HasOne for Rc<T>
where
T: HasOne,
{
#[inline]
fn one() -> Self {
Rc::new(<T as HasOne>::one())
}
}
pub trait AddByRef<Rhs = Self> {
fn add_by_ref(&self, other: &Rhs) -> Self;
}
impl<T> AddByRef for T
where
for<'a> &'a T: Add<Output = T>,
{
#[inline]
fn add_by_ref(&self, other: &Self) -> Self {
self.add(other)
}
}
pub trait NegByRef {
fn neg_by_ref(&self) -> Self;
}
impl<T> NegByRef for T
where
for<'a> &'a T: Neg<Output = T>,
{
#[inline]
fn neg_by_ref(&self) -> Self {
self.neg()
}
}
pub trait AddAssignByRef<Rhs = Self> {
fn add_assign_by_ref(&mut self, other: &Rhs);
}
impl<T> AddAssignByRef for T
where
for<'a> T: AddAssign<&'a T>,
{
#[inline]
fn add_assign_by_ref(&mut self, other: &Self) {
self.add_assign(other)
}
}
pub trait MulByRef<Rhs = Self> {
type Output;
fn mul_by_ref(&self, other: &Rhs) -> Self::Output;
}
impl<T> MulByRef<T> for T
where
for<'a> &'a T: Mul<Output = Self>,
{
type Output = Self;
#[inline]
fn mul_by_ref(&self, other: &Self) -> Self::Output {
self.mul(other)
}
}
pub trait SemigroupValue: Clone + Eq + SizeOf + AddByRef + AddAssignByRef + 'static {}
impl<T> SemigroupValue for T where T: Clone + Eq + SizeOf + AddByRef + AddAssignByRef + 'static {}
pub trait MonoidValue: SemigroupValue + HasZero {}
impl<T> MonoidValue for T where T: SemigroupValue + HasZero {}
pub trait GroupValue: MonoidValue + Neg<Output = Self> + NegByRef {}
impl<T> GroupValue for T where T: MonoidValue + Neg<Output = Self> + NegByRef {}
pub trait RingValue: GroupValue + Mul<Output = Self> + MulByRef<Output = Self> + HasOne {}
impl<T> RingValue for T where T: GroupValue + Mul<Output = Self> + MulByRef<Output = Self> + HasOne {}
pub trait ZRingValue: RingValue {
fn ge0(&self) -> bool;
fn le0(&self) -> bool;
}
impl<T> ZRingValue for T
where
T: RingValue + Ord,
{
#[inline]
fn ge0(&self) -> bool {
*self >= Self::zero()
}
#[inline]
fn le0(&self) -> bool {
*self <= Self::zero()
}
}
impl MulByRef<isize> for i8 {
type Output = Self;
#[inline]
fn mul_by_ref(&self, w: &isize) -> Self::Output {
(*self as isize * w) as Self
}
}
impl MulByRef<isize> for i16 {
type Output = Self;
#[inline]
fn mul_by_ref(&self, w: &isize) -> Self::Output {
(*self as isize * w) as Self
}
}
impl MulByRef<isize> for i32 {
type Output = Self;
#[inline]
fn mul_by_ref(&self, w: &isize) -> Self::Output {
(*self as isize * w) as Self
}
}
impl MulByRef<isize> for i64 {
type Output = Self;
#[inline]
fn mul_by_ref(&self, w: &isize) -> Self::Output {
(*self as isize * w) as Self
}
}
impl MulByRef<isize> for f32 {
type Output = Self;
#[inline]
fn mul_by_ref(&self, w: &isize) -> Self::Output {
*self * ((*w) as f32)
}
}
impl MulByRef<isize> for f64 {
type Output = Self;
#[inline]
fn mul_by_ref(&self, w: &isize) -> Self::Output {
*self * ((*w) as f64)
}
}
impl MulByRef<isize> for F32 {
type Output = Self;
#[inline]
fn mul_by_ref(&self, w: &isize) -> Self::Output {
*self * ((*w) as f32)
}
}
impl MulByRef<isize> for F64 {
type Output = Self;
#[inline]
fn mul_by_ref(&self, w: &isize) -> Self::Output {
*self * ((*w) as f64)
}
}
impl MulByRef<isize> for Decimal {
type Output = Self;
#[inline]
fn mul_by_ref(&self, w: &isize) -> Self::Output {
*self * Decimal::from(*w)
}
}
impl MulByRef<i64> for i8 {
type Output = Self;
#[inline]
fn mul_by_ref(&self, w: &i64) -> Self::Output {
(*self as i64 * w) as Self
}
}
impl MulByRef<i64> for i16 {
type Output = Self;
#[inline]
fn mul_by_ref(&self, w: &i64) -> Self::Output {
(*self as i64 * w) as Self
}
}
impl MulByRef<i64> for i32 {
type Output = Self;
#[inline]
fn mul_by_ref(&self, w: &i64) -> Self::Output {
(*self as i64 * w) as Self
}
}
impl MulByRef<i64> for isize {
type Output = Self;
#[inline]
fn mul_by_ref(&self, w: &i64) -> Self::Output {
(*self as i64 * w) as Self
}
}
impl MulByRef<i64> for f32 {
type Output = Self;
#[inline]
fn mul_by_ref(&self, w: &i64) -> Self::Output {
*self * ((*w) as f32)
}
}
impl MulByRef<i64> for f64 {
type Output = Self;
#[inline]
fn mul_by_ref(&self, w: &i64) -> Self::Output {
*self * ((*w) as f64)
}
}
impl MulByRef<i64> for F32 {
type Output = Self;
#[inline]
fn mul_by_ref(&self, w: &i64) -> Self::Output {
*self * ((*w) as f32)
}
}
impl MulByRef<i64> for F64 {
type Output = Self;
#[inline]
fn mul_by_ref(&self, w: &i64) -> Self::Output {
*self * ((*w) as f64)
}
}
impl MulByRef<i64> for Decimal {
type Output = Self;
#[inline]
fn mul_by_ref(&self, w: &i64) -> Self::Output {
*self * Decimal::from(*w)
}
}
impl MulByRef<i32> for i8 {
type Output = Self;
#[inline]
fn mul_by_ref(&self, w: &i32) -> Self::Output {
(*self as i32 * w) as Self
}
}
impl MulByRef<i32> for i16 {
type Output = Self;
#[inline]
fn mul_by_ref(&self, w: &i32) -> Self::Output {
(*self as i32 * w) as Self
}
}
impl MulByRef<i32> for i64 {
type Output = Self;
#[inline]
fn mul_by_ref(&self, w: &i32) -> Self::Output {
(*self as i32 * w) as Self
}
}
impl MulByRef<i32> for isize {
type Output = Self;
#[inline]
fn mul_by_ref(&self, w: &i32) -> Self::Output {
(*self as i32 * w) as Self
}
}
impl MulByRef<i32> for f32 {
type Output = Self;
#[inline]
fn mul_by_ref(&self, w: &i32) -> Self::Output {
*self * ((*w) as f32)
}
}
impl MulByRef<i32> for f64 {
type Output = Self;
#[inline]
fn mul_by_ref(&self, w: &i32) -> Self::Output {
*self * ((*w) as f64)
}
}
impl MulByRef<i32> for F32 {
type Output = Self;
#[inline]
fn mul_by_ref(&self, w: &i32) -> Self::Output {
*self * ((*w) as f32)
}
}
impl MulByRef<i32> for F64 {
type Output = Self;
#[inline]
fn mul_by_ref(&self, w: &i32) -> Self::Output {
*self * ((*w) as f64)
}
}
impl MulByRef<i32> for Decimal {
type Output = Self;
#[inline]
fn mul_by_ref(&self, w: &i32) -> Self::Output {
*self * Decimal::from(*w)
}
}
trait OptionWeightType {}
impl OptionWeightType for isize {}
impl OptionWeightType for i8 {}
impl OptionWeightType for i16 {}
impl OptionWeightType for i32 {}
impl OptionWeightType for i64 {}
impl OptionWeightType for f32 {}
impl OptionWeightType for f64 {}
impl OptionWeightType for F32 {}
impl OptionWeightType for F64 {}
impl OptionWeightType for Decimal {}
impl OptionWeightType for Present {}
impl<T, S> MulByRef<S> for Option<T>
where
T: MulByRef<S, Output = T>,
S: OptionWeightType,
{
type Output = Self;
#[inline]
fn mul_by_ref(&self, rhs: &S) -> Self::Output {
self.as_ref().map(|lhs| lhs.mul_by_ref(rhs))
}
}
pub trait Semigroup<V> {
fn combine(left: &V, right: &V) -> V;
fn combine_opt(left: &Option<V>, right: &Option<V>) -> Option<V>
where
V: Clone,
{
if let Some(left) = left {
if let Some(right) = right {
Some(Self::combine(left, right))
} else {
Some(left.clone())
}
} else {
right.clone()
}
}
}
#[derive(Clone)]
pub struct DefaultSemigroup<V>(PhantomData<V>);
impl<V> Semigroup<V> for DefaultSemigroup<V>
where
V: SemigroupValue,
{
fn combine(left: &V, right: &V) -> V {
left.add_by_ref(right)
}
}
#[derive(Clone)]
pub struct UnimplementedSemigroup<V>(PhantomData<V>);
impl<V> Semigroup<V> for UnimplementedSemigroup<V> {
fn combine(_left: &V, _right: &V) -> V {
unimplemented!()
}
}
#[cfg(test)]
mod integer_ring_tests {
use super::*;
#[test]
fn fixed_integer_tests() {
assert_eq!(0, <i64 as HasZero>::zero());
assert_eq!(1, <i64 as HasOne>::one());
let two = <i64 as HasOne>::one().add_by_ref(&<i64 as HasOne>::one());
assert_eq!(2, two);
assert_eq!(-2, two.neg_by_ref());
assert_eq!(-4, two.mul_by_ref(&two.neg_by_ref()));
}
#[test]
fn fixed_isize_tests() {
assert_eq!(0, <isize as HasZero>::zero());
assert_eq!(1, <isize as HasOne>::one());
let two = <isize as HasOne>::one().add_by_ref(&<isize as HasOne>::one());
assert_eq!(2, two);
assert_eq!(-2, two.neg_by_ref());
assert_eq!(-4, two.mul_by_ref(&two.neg_by_ref()));
}
#[test]
fn fixed_i64_tests() {
assert_eq!(0, <i64 as HasZero>::zero());
assert_eq!(1, <i64 as HasOne>::one());
let two = <i64 as HasOne>::one().add_by_ref(&<i64 as HasOne>::one());
assert_eq!(2, two);
assert_eq!(-2, two.neg_by_ref());
assert_eq!(-4, two.mul_by_ref(&two.neg_by_ref()));
}
}