11use std:: fmt;
2+ use std:: usize;
23use alloc:: vec:: Vec ;
34
45use super :: combinations:: { Combinations , combinations} ;
6+ use super :: size_hint;
57
68/// An iterator to iterate through the powerset of the elements from an iterator.
79///
@@ -10,28 +12,33 @@ use super::combinations::{Combinations, combinations};
1012#[ must_use = "iterator adaptors are lazy and do nothing unless consumed" ]
1113pub struct Powerset < I : Iterator > {
1214 combs : Combinations < I > ,
15+ // Iterator `position` (equal to count of yielded elements).
16+ pos : usize ,
1317}
1418
1519impl < I > Clone for Powerset < I >
1620 where I : Clone + Iterator ,
1721 I :: Item : Clone ,
1822{
19- clone_fields ! ( combs) ;
23+ clone_fields ! ( combs, pos ) ;
2024}
2125
2226impl < I > fmt:: Debug for Powerset < I >
2327 where I : Iterator + fmt:: Debug ,
2428 I :: Item : fmt:: Debug ,
2529{
26- debug_fmt_fields ! ( Powerset , combs) ;
30+ debug_fmt_fields ! ( Powerset , combs, pos ) ;
2731}
2832
2933/// Create a new `Powerset` from a clonable iterator.
3034pub fn powerset < I > ( src : I ) -> Powerset < I >
3135 where I : Iterator ,
3236 I :: Item : Clone ,
3337{
34- Powerset { combs : combinations ( src, 0 ) }
38+ Powerset {
39+ combs : combinations ( src, 0 ) ,
40+ pos : 0 ,
41+ }
3542}
3643
3744impl < I > Iterator for Powerset < I >
@@ -43,14 +50,34 @@ impl<I> Iterator for Powerset<I>
4350
4451 fn next ( & mut self ) -> Option < Self :: Item > {
4552 if let Some ( elt) = self . combs . next ( ) {
53+ self . pos = self . pos . saturating_add ( 1 ) ;
4654 Some ( elt)
4755 } else if self . combs . k ( ) < self . combs . n ( )
4856 || self . combs . k ( ) == 0
4957 {
5058 self . combs . reset ( self . combs . k ( ) + 1 ) ;
51- self . combs . next ( )
59+ self . combs . next ( ) . map ( |elt| {
60+ self . pos = self . pos . saturating_add ( 1 ) ;
61+ elt
62+ } )
5263 } else {
5364 None
5465 }
5566 }
67+
68+ fn size_hint ( & self ) -> ( usize , Option < usize > ) {
69+ // Total bounds for source iterator.
70+ let src_total = size_hint:: add_scalar ( self . combs . src ( ) . size_hint ( ) , self . combs . n ( ) ) ;
71+
72+ // Total bounds for self ( length(powerset(set) == 2 ^ length(set) )
73+ let self_total = size_hint:: pow_scalar_base ( 2 , src_total) ;
74+
75+ if self . pos < usize:: MAX {
76+ // Subtract count of elements already yielded from total.
77+ size_hint:: sub_scalar ( self_total, self . pos )
78+ } else {
79+ // Fallback: self.pos is saturated and no longer reliable.
80+ ( 0 , self_total. 1 )
81+ }
82+ }
5683}
0 commit comments