yui_core/conc/lc/
lc_key.rs1use std::ops::Mul;
6use derive_more::Display;
7use itertools::Either;
8
9use crate::lc::Lc;
10use crate::abst::{MathType, IndexType, Ring, RingOps};
11
12pub trait LcKey: MathType + IndexType {}
15
16pub trait LcMulKey: LcKey {
23 fn mul_ref(&self, rhs: &Self) -> Self;
24}
25
26impl<X> LcMulKey for X
27where X: LcKey, for<'x> &'x X: Mul<Output = X> {
28 fn mul_ref(&self, rhs: &Self) -> Self {
29 self * rhs
30 }
31}
32
33#[derive(Debug, Display, Default, Hash, PartialEq, Eq, Clone, PartialOrd, Ord)]
37#[display("<{}>", _0)]
38#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
39#[cfg_attr(feature = "serde", serde(transparent))]
40pub struct AsKey<T>(pub T) where T: IndexType;
41
42impl<T> From<T> for AsKey<T>
43where T: IndexType {
44 fn from(value: T) -> Self {
45 Self(value)
46 }
47}
48
49impl<T> MathType for AsKey<T>
50where T: IndexType {
51 fn math_symbol() -> String {
52 let full_name = std::any::type_name::<T>();
53 let name = full_name.split("::").last().unwrap_or(full_name);
54 format!("Free<{}>", name)
55 }
56}
57
58impl<T> LcKey for AsKey<T>
59where T: IndexType {}
60
61#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
64pub struct EitherKey<X, Y>(Either<X, Y>) where X: LcKey, Y: LcKey;
65
66impl<X, Y> EitherKey<X, Y> where X: LcKey, Y: LcKey {
67 pub fn from_left(x: X) -> Self {
68 Self(Either::Left(x))
69 }
70
71 pub fn from_right(y: Y) -> Self {
72 Self(Either::Right(y))
73 }
74
75 pub fn entity(&self) -> Either<&X, &Y> {
76 match &self.0 {
77 Either::Left(x) => Either::Left(x),
78 Either::Right(y) => Either::Right(y),
79 }
80 }
81
82 pub fn is_left(&self) -> bool {
83 matches!(self.0, Either::Left(_))
84 }
85
86 pub fn is_right(&self) -> bool {
87 matches!(self.0, Either::Right(_))
88 }
89
90 pub fn inner(&self) -> &Either<X, Y> {
91 &self.0
92 }
93
94 pub fn into_left(self) -> X {
95 let Either::Left(x) = self.0 else {
96 panic!();
97 };
98 x
99 }
100
101 pub fn into_right(self) -> Y {
102 let Either::Right(y) = self.0 else {
103 panic!();
104 };
105 y
106 }
107}
108
109impl<X, Y> From<Either<X, Y>> for EitherKey<X, Y> where X: LcKey, Y: LcKey {
110 fn from(e: Either<X, Y>) -> Self {
111 Self(e)
112 }
113}
114
115impl<X, Y> From<EitherKey<X, Y>> for Either<X, Y> where X: LcKey, Y: LcKey {
116 fn from(e: EitherKey<X, Y>) -> Self {
117 e.0
118 }
119}
120
121impl<X, Y> Default for EitherKey<X, Y> where X: LcKey, Y: LcKey {
122 fn default() -> Self {
123 Self(Either::Left(X::default()))
124 }
125}
126
127impl <X, Y> std::fmt::Display for EitherKey<X, Y> where X: LcKey, Y: LcKey {
128 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
129 match &self.0 {
130 Either::Left(x) => std::fmt::Display::fmt(x, f),
131 Either::Right(y) => std::fmt::Display::fmt(y, f),
132 }
133 }
134}
135
136impl<X, Y> MathType for EitherKey<X, Y> where X: LcKey, Y: LcKey {
137 fn math_symbol() -> String {
138 if X::math_symbol() == Y::math_symbol() {
139 X::math_symbol()
140 } else {
141 format!("E({},{})", X::math_symbol(), Y::math_symbol())
142 }
143 }
144}
145
146impl <X, Y> LcKey for EitherKey<X, Y> where X: LcKey, Y: LcKey {
147}
148
149pub fn split_lr<X, Y, R>(z: &Lc<EitherKey<X, Y>, R>) -> (Lc<X, R>, Lc<Y, R>)
150where X: LcKey, Y: LcKey, R: Ring, for<'x> &'x R: RingOps<R>{
151 let mut x = vec![];
152 let mut y = vec![];
153 for (e, r) in z.iter() {
154 if e.is_left() {
155 x.push((e.clone().into_left(), r.clone()));
156 } else {
157 y.push((e.clone().into_right(), r.clone()));
158 }
159 }
160 (Lc::from_iter(x), Lc::from_iter(y))
161}
162
163#[cfg(test)]
164mod tests {
165 use super::*;
166 use crate::lc::AsKey; #[test]
169 fn test_either_key() {
170 type T = EitherKey<AsKey<i32>, AsKey<String>>;
171 let a = T::from_left(AsKey(42));
172 let b = T::from_right(AsKey("hello".to_string()));
173
174 assert_eq!(a.to_string(), "<42>");
175 assert_eq!(b.to_string(), "<hello>");
176 }
177}