11using System ;
22using System . Collections ;
33using System . Collections . Generic ;
4+ using System . Linq ;
45using System . Runtime . CompilerServices ;
56
67namespace Vectorial1024 . Collections . Generic
@@ -27,6 +28,8 @@ internal DataBox(TData value)
2728
2829 internal List < DataBox < TValue > ? > _list = new List < DataBox < TValue > ? > ( ) ;
2930
31+ internal bool [ ] _issetLookup ;
32+
3033 internal int _actualCount ;
3134
3235 // the version of the DictionaryList, to ensure the enumerator can work correctly
@@ -37,6 +40,8 @@ internal DataBox(TData value)
3740 /// </summary>
3841 public DictionaryList ( )
3942 {
43+ var capacity = Capacity ;
44+ _issetLookup = new bool [ capacity ] ;
4045 }
4146
4247 /// <summary>
@@ -48,6 +53,7 @@ public DictionaryList(DictionaryList<TValue> collection)
4853 {
4954 _list = new List < DataBox < TValue > ? > ( collection . _list ) ;
5055 _actualCount = collection . _actualCount ;
56+ _issetLookup = ( bool [ ] ) collection . _issetLookup . Clone ( ) ;
5157 }
5258
5359 /// <summary>
@@ -57,6 +63,7 @@ public DictionaryList(DictionaryList<TValue> collection)
5763 public DictionaryList ( int capacity )
5864 {
5965 _list = new List < DataBox < TValue > ? > ( capacity ) ;
66+ _issetLookup = new bool [ capacity ] ;
6067 }
6168
6269 /// <summary>
@@ -88,6 +95,7 @@ public TValue this[int index]
8895 set
8996 {
9097 _list [ index ] = new DataBox < TValue > ( value ) ;
98+ _issetLookup [ index ] = true ;
9199 }
92100 }
93101
@@ -98,9 +106,17 @@ public TValue this[int index]
98106 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
99107 public void Add ( TValue value )
100108 {
109+ var nextIndex = _list . Count ;
101110 _list . Add ( new DataBox < TValue > ( value ) ) ;
102111 _actualCount ++ ;
103112 _version ++ ;
113+
114+ // react to resizing if happened
115+ if ( _issetLookup . Length != _list . Capacity )
116+ {
117+ Array . Resize ( ref _issetLookup , _list . Capacity ) ;
118+ }
119+ _issetLookup [ nextIndex ] = true ;
104120 }
105121
106122 /// <summary>
@@ -120,6 +136,7 @@ public void UnsetAt(int index)
120136
121137 _list [ index ] = null ;
122138 _actualCount -- ;
139+ _issetLookup [ index ] = false ;
123140 }
124141
125142 /// <summary>
@@ -139,7 +156,15 @@ public bool ContainsIndex(int index)
139156 return false ;
140157 }
141158 // we might have it
142- return _list [ index ] . HasValue ;
159+ return IndexIsSet ( index ) ;
160+ }
161+
162+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
163+ internal bool IndexIsSet ( int index )
164+ {
165+ // does not check for index range, for internal use where we are very sure it does not cause range overflow
166+ // we force-inline it to waive this method call
167+ return _issetLookup [ index ] ;
143168 }
144169
145170 #region CompactAndTrim
@@ -151,6 +176,7 @@ public void Clear()
151176 {
152177 _list . Clear ( ) ;
153178 _actualCount = 0 ;
179+ _issetLookup = new bool [ Capacity ] ;
154180 }
155181
156182 /// <summary>
@@ -172,6 +198,7 @@ public void CompactAndTrimExcess()
172198 _list = newList ;
173199 _actualCount = newList . Count ;
174200 _version ++ ;
201+ _issetLookup = Enumerable . Repeat ( true , _actualCount ) . ToArray ( ) ;
175202 }
176203
177204 #endregion
@@ -185,6 +212,7 @@ internal struct DictionaryListEnumerator : IEnumerator<KeyValuePair<int, TValue>
185212 private KeyValuePair < int , TValue > _current ;
186213 private readonly int _size ;
187214 private readonly int _version ;
215+ private readonly bool [ ] _issetLookup ;
188216
189217 internal DictionaryListEnumerator ( DictionaryList < TValue > dictList )
190218 {
@@ -193,6 +221,7 @@ internal DictionaryListEnumerator(DictionaryList<TValue> dictList)
193221 _current = default ;
194222 _size = _dictList . _list . Count ;
195223 _version = dictList . _version ;
224+ _issetLookup = _dictList . _issetLookup ;
196225 }
197226
198227 public bool MoveNext ( )
@@ -201,7 +230,7 @@ public bool MoveNext()
201230 var theDictList = _dictList ;
202231 while ( _version == theDictList . _version && ( uint ) iterIndex < ( uint ) _size )
203232 {
204- if ( ! theDictList . ContainsIndex ( iterIndex ) )
233+ if ( ! theDictList . IndexIsSet ( iterIndex ) )
205234 {
206235 // not set; find the next one!
207236 iterIndex ++ ;
0 commit comments