Skip to main content

webgraph/labels/
proj.rs

1/*
2 * SPDX-FileCopyrightText: 2023 Sebastiano Vigna
3 *
4 * SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
5 */
6
7/*!
8
9Left and right projections.
10
11The two structures in this module, [`Left`] and [`Right`], provide
12projection of a labeling whose labels are pairs. In particular,
13`Left(Zip(g,h))` is the same labeling as `g` and
14`Right(Zip(g,h))` is the same labeling as `h`.
15
16*/
17use crate::prelude::{
18    LenderIntoIterator, LenderLabel, NodeLabelsLender, Pair, RandomAccessGraph,
19    RandomAccessLabeling, SequentialGraph, SequentialLabeling, SortedIterator, SortedLender,
20};
21use crate::traits::SplitLabeling;
22use lender::{ExactSizeLender, IntoLender, Lend, Lender, Lending, unsafe_assume_covariance};
23
24/// The projection onto the first component of a pair.
25#[derive(Clone, Debug, PartialEq, Eq, Ord, PartialOrd)]
26pub struct Left<S: SequentialLabeling>(pub S)
27where
28    S::Label: Pair;
29
30#[derive(Clone, Debug, PartialEq, Eq, Ord, PartialOrd)]
31pub struct LeftIterator<L>(pub L);
32
33impl<'succ, L> NodeLabelsLender<'succ> for LeftIterator<L>
34where
35    L: Lender + for<'next> NodeLabelsLender<'next>,
36    for<'next> LenderLabel<'next, L>: Pair,
37{
38    type Label = <LenderLabel<'succ, L> as Pair>::Left;
39    type IntoIterator = IntoLeftSucc<<L as NodeLabelsLender<'succ>>::IntoIterator>;
40}
41
42impl<'succ, L> Lending<'succ> for LeftIterator<L>
43where
44    L: Lender + for<'next> NodeLabelsLender<'next>,
45    for<'next> LenderLabel<'next, L>: Pair,
46{
47    type Lend = (usize, LenderIntoIterator<'succ, Self>);
48}
49
50impl<L: ExactSizeLender> ExactSizeLender for LeftIterator<L>
51where
52    L: Lender + for<'next> NodeLabelsLender<'next>,
53    for<'next> LenderLabel<'next, L>: Pair,
54{
55    #[inline(always)]
56    fn len(&self) -> usize {
57        self.0.len()
58    }
59
60    #[inline(always)]
61    fn is_empty(&self) -> bool {
62        self.0.is_empty()
63    }
64}
65
66#[derive(Clone, Debug, PartialEq, Eq, Ord, PartialOrd)]
67pub struct IntoLeftSucc<I: IntoIterator>(pub I)
68where
69    I::Item: Pair;
70
71#[derive(Clone, Debug, PartialEq, Eq, Ord, PartialOrd)]
72pub struct LeftSucc<I: Iterator>(pub I)
73where
74    I::Item: Pair;
75
76impl<I: Iterator> Iterator for LeftSucc<I>
77where
78    I::Item: Pair,
79{
80    type Item = <I::Item as Pair>::Left;
81
82    #[inline(always)]
83    fn next(&mut self) -> Option<Self::Item> {
84        self.0.next().map(|x| x.into_pair().0)
85    }
86
87    #[inline(always)]
88    fn count(self) -> usize {
89        self.0.count()
90    }
91}
92
93impl<I: ExactSizeIterator> ExactSizeIterator for LeftSucc<I>
94where
95    I::Item: Pair,
96{
97    #[inline(always)]
98    fn len(&self) -> usize {
99        self.0.len()
100    }
101}
102
103impl<I: DoubleEndedIterator> DoubleEndedIterator for LeftSucc<I>
104where
105    I::Item: Pair,
106{
107    #[inline(always)]
108    fn next_back(&mut self) -> Option<Self::Item> {
109        self.0.next_back().map(|x| x.into_pair().0)
110    }
111
112    #[inline(always)]
113    fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
114        self.0.nth_back(n).map(|x| x.into_pair().0)
115    }
116}
117
118impl<I: IntoIterator> IntoIterator for IntoLeftSucc<I>
119where
120    I::Item: Pair,
121{
122    type Item = <I::Item as Pair>::Left;
123    type IntoIter = LeftSucc<I::IntoIter>;
124
125    #[inline(always)]
126    fn into_iter(self) -> Self::IntoIter {
127        LeftSucc(self.0.into_iter())
128    }
129}
130
131impl<L> Lender for LeftIterator<L>
132where
133    L: Lender + for<'next> NodeLabelsLender<'next>,
134    for<'next> LenderLabel<'next, L>: Pair,
135{
136    // SAFETY: the lend is covariant as it projects the left component from the
137    // underlying covariant lender L.
138    unsafe_assume_covariance!();
139
140    #[inline(always)]
141    fn next(&mut self) -> Option<Lend<'_, Self>> {
142        self.0.next().map(|x| {
143            let (node, succ) = x.into_pair();
144            (node, IntoLeftSucc(succ))
145        })
146    }
147
148    #[inline(always)]
149    fn size_hint(&self) -> (usize, Option<usize>) {
150        self.0.size_hint()
151    }
152}
153
154impl<'a, S: SequentialLabeling> IntoLender for &'a Left<S>
155where
156    S::Label: Pair,
157{
158    type Lender = <Left<S> as SequentialLabeling>::Lender<'a>;
159
160    #[inline(always)]
161    fn into_lender(self) -> Self::Lender {
162        self.iter()
163    }
164}
165
166impl<G> SplitLabeling for Left<G>
167where
168    G: SequentialLabeling + SplitLabeling,
169    G::Label: Pair,
170{
171    type SplitLender<'a>
172        = LeftIterator<G::SplitLender<'a>>
173    where
174        Self: 'a;
175    type IntoIterator<'a>
176        = core::iter::Map<
177        <G::IntoIterator<'a> as IntoIterator>::IntoIter,
178        fn(G::SplitLender<'a>) -> Self::SplitLender<'a>,
179    >
180    where
181        Self: 'a;
182
183    fn split_iter(&self, how_many: usize) -> Self::IntoIterator<'_> {
184        self.0.split_iter(how_many).into_iter().map(LeftIterator)
185    }
186}
187
188impl<S: SequentialLabeling> SequentialLabeling for Left<S>
189where
190    S::Label: Pair,
191{
192    type Label = <S::Label as Pair>::Left;
193
194    type Lender<'node>
195        = LeftIterator<S::Lender<'node>>
196    where
197        Self: 'node;
198
199    #[inline(always)]
200    fn num_nodes(&self) -> usize {
201        self.0.num_nodes()
202    }
203
204    #[inline(always)]
205    fn iter_from(&self, from: usize) -> Self::Lender<'_> {
206        LeftIterator(self.0.iter_from(from))
207    }
208
209    #[inline(always)]
210    fn num_arcs_hint(&self) -> Option<u64> {
211        self.0.num_arcs_hint()
212    }
213}
214
215impl<R: RandomAccessLabeling> RandomAccessLabeling for Left<R>
216where
217    R::Label: Pair,
218{
219    type Labels<'succ>
220        = IntoLeftSucc<<R as RandomAccessLabeling>::Labels<'succ>>
221    where
222        Self: 'succ;
223
224    #[inline(always)]
225    fn num_arcs(&self) -> u64 {
226        self.0.num_arcs()
227    }
228
229    #[inline(always)]
230    fn labels(&self, node_id: usize) -> <Self as RandomAccessLabeling>::Labels<'_> {
231        IntoLeftSucc(self.0.labels(node_id))
232    }
233
234    #[inline(always)]
235    fn outdegree(&self, _node_id: usize) -> usize {
236        self.0.outdegree(_node_id)
237    }
238}
239
240impl<S: SequentialLabeling> SequentialGraph for Left<S> where S::Label: Pair<Left = usize> {}
241
242impl<R: RandomAccessLabeling> RandomAccessGraph for Left<R> where R::Label: Pair<Left = usize> {}
243
244unsafe impl<L: SortedLender> SortedLender for LeftIterator<L>
245where
246    L: Lender + for<'next> NodeLabelsLender<'next>,
247    for<'next> LenderLabel<'next, L>: Pair,
248{
249}
250
251unsafe impl<I: SortedIterator> SortedIterator for LeftSucc<I> where I::Item: Pair {}
252
253/// The projection onto the second component of a pair.
254#[derive(Clone, Debug, PartialEq, Eq, Ord, PartialOrd)]
255pub struct Right<S: SequentialLabeling>(pub S)
256where
257    S::Label: Pair;
258
259#[derive(Clone, Debug, PartialEq, Eq, Ord, PartialOrd)]
260pub struct RightIterator<L>(pub L);
261
262impl<'succ, L> NodeLabelsLender<'succ> for RightIterator<L>
263where
264    L: Lender + for<'next> NodeLabelsLender<'next>,
265    for<'next> LenderLabel<'next, L>: Pair,
266{
267    type Label = <LenderLabel<'succ, L> as Pair>::Right;
268    type IntoIterator = IntoRightSucc<<L as NodeLabelsLender<'succ>>::IntoIterator>;
269}
270
271impl<'succ, L> Lending<'succ> for RightIterator<L>
272where
273    L: Lender + for<'next> NodeLabelsLender<'next>,
274    for<'next> LenderLabel<'next, L>: Pair,
275{
276    type Lend = (usize, LenderIntoIterator<'succ, Self>);
277}
278
279impl<L: ExactSizeLender> ExactSizeLender for RightIterator<L>
280where
281    L: Lender + for<'next> NodeLabelsLender<'next>,
282    for<'next> LenderLabel<'next, L>: Pair,
283{
284    #[inline(always)]
285    fn len(&self) -> usize {
286        self.0.len()
287    }
288
289    #[inline(always)]
290    fn is_empty(&self) -> bool {
291        self.0.is_empty()
292    }
293}
294
295#[derive(Clone, Debug, PartialEq, Eq, Ord, PartialOrd)]
296pub struct IntoRightSucc<I: IntoIterator>(pub I)
297where
298    I::Item: Pair;
299
300#[derive(Clone, Debug, PartialEq, Eq, Ord, PartialOrd)]
301pub struct RightSucc<I: Iterator>(pub I)
302where
303    I::Item: Pair;
304
305impl<I: Iterator> Iterator for RightSucc<I>
306where
307    I::Item: Pair,
308{
309    type Item = <I::Item as Pair>::Right;
310
311    #[inline(always)]
312    fn next(&mut self) -> Option<Self::Item> {
313        self.0.next().map(|x| x.into_pair().1)
314    }
315
316    #[inline(always)]
317    fn count(self) -> usize {
318        self.0.count()
319    }
320}
321
322impl<I: ExactSizeIterator> ExactSizeIterator for RightSucc<I>
323where
324    I::Item: Pair,
325{
326    #[inline(always)]
327    fn len(&self) -> usize {
328        self.0.len()
329    }
330}
331
332impl<I: DoubleEndedIterator> DoubleEndedIterator for RightSucc<I>
333where
334    I::Item: Pair,
335{
336    #[inline(always)]
337    fn next_back(&mut self) -> Option<Self::Item> {
338        self.0.next_back().map(|x| x.into_pair().1)
339    }
340
341    #[inline(always)]
342    fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
343        self.0.nth_back(n).map(|x| x.into_pair().1)
344    }
345}
346
347impl<I: IntoIterator> IntoIterator for IntoRightSucc<I>
348where
349    I::Item: Pair,
350{
351    type Item = <I::Item as Pair>::Right;
352    type IntoIter = RightSucc<I::IntoIter>;
353
354    #[inline(always)]
355    fn into_iter(self) -> Self::IntoIter {
356        RightSucc(self.0.into_iter())
357    }
358}
359
360impl<L> Lender for RightIterator<L>
361where
362    L: Lender + for<'next> NodeLabelsLender<'next>,
363    for<'next> LenderLabel<'next, L>: Pair,
364{
365    // SAFETY: the lend is covariant as it projects the right component from the
366    // underlying covariant lender L.
367    unsafe_assume_covariance!();
368
369    #[inline(always)]
370    fn next(&mut self) -> Option<Lend<'_, Self>> {
371        self.0.next().map(|x| {
372            let (node, succ) = x.into_pair();
373            (node, IntoRightSucc(succ))
374        })
375    }
376
377    #[inline(always)]
378    fn size_hint(&self) -> (usize, Option<usize>) {
379        self.0.size_hint()
380    }
381}
382
383impl<'a, S: SequentialLabeling> IntoLender for &'a Right<S>
384where
385    S::Label: Pair,
386{
387    type Lender = <Right<S> as SequentialLabeling>::Lender<'a>;
388
389    #[inline(always)]
390    fn into_lender(self) -> Self::Lender {
391        self.iter()
392    }
393}
394
395impl<G> SplitLabeling for Right<G>
396where
397    G: SequentialLabeling + SplitLabeling,
398    G::Label: Pair,
399{
400    type SplitLender<'a>
401        = RightIterator<G::SplitLender<'a>>
402    where
403        Self: 'a;
404    type IntoIterator<'a>
405        = core::iter::Map<
406        <G::IntoIterator<'a> as IntoIterator>::IntoIter,
407        fn(G::SplitLender<'a>) -> Self::SplitLender<'a>,
408    >
409    where
410        Self: 'a;
411
412    fn split_iter(&self, how_many: usize) -> Self::IntoIterator<'_> {
413        self.0.split_iter(how_many).into_iter().map(RightIterator)
414    }
415}
416
417impl<S: SequentialLabeling> SequentialLabeling for Right<S>
418where
419    S::Label: Pair,
420{
421    type Label = <S::Label as Pair>::Right;
422
423    type Lender<'node>
424        = RightIterator<S::Lender<'node>>
425    where
426        Self: 'node;
427
428    #[inline(always)]
429    fn num_nodes(&self) -> usize {
430        self.0.num_nodes()
431    }
432
433    #[inline(always)]
434    fn num_arcs_hint(&self) -> Option<u64> {
435        self.0.num_arcs_hint()
436    }
437
438    #[inline(always)]
439    fn iter_from(&self, from: usize) -> Self::Lender<'_> {
440        RightIterator(self.0.iter_from(from))
441    }
442}
443
444impl<R: RandomAccessLabeling> RandomAccessLabeling for Right<R>
445where
446    R::Label: Pair,
447{
448    type Labels<'succ>
449        = IntoRightSucc<<R as RandomAccessLabeling>::Labels<'succ>>
450    where
451        Self: 'succ;
452
453    #[inline(always)]
454    fn num_arcs(&self) -> u64 {
455        self.0.num_arcs()
456    }
457
458    #[inline(always)]
459    fn labels(&self, node_id: usize) -> <Self as RandomAccessLabeling>::Labels<'_> {
460        IntoRightSucc(self.0.labels(node_id))
461    }
462
463    #[inline(always)]
464    fn outdegree(&self, _node_id: usize) -> usize {
465        self.0.outdegree(_node_id)
466    }
467}
468
469impl<S: SequentialLabeling> SequentialGraph for Right<S> where S::Label: Pair<Right = usize> {}
470
471impl<R: RandomAccessLabeling> RandomAccessGraph for Right<R> where R::Label: Pair<Right = usize> {}
472
473unsafe impl<L: SortedLender> SortedLender for RightIterator<L>
474where
475    L: Lender + for<'next> NodeLabelsLender<'next>,
476    for<'next> LenderLabel<'next, L>: Pair,
477{
478}
479
480unsafe impl<I: SortedIterator> SortedIterator for RightSucc<I> where I::Item: Pair {}