19 using System.Collections.Generic;
22 namespace Deveel.Data.Util {
24 internal static readonly IEqualityComparer<T> _comparer = EqualityComparer<T>.Default;
26 private static readonly T[][] _emptyArray =
new T[0][];
34 : this(length, default(T)) {
38 : this(length, defaultValue,
BigArray.DefaultBlockLength) {
42 : this(length, default(T), blockLength) {
45 public BigArray(
long length, T defaultValue,
int blockLength) {
46 if (blockLength < 1024 * 1024)
47 throw new ArgumentOutOfRangeException(
"blockSize");
49 _defaultValue = defaultValue;
50 _blockLength = blockLength;
54 _firstArray = _emptyArray;
62 numBlocks = (int)(length / blockLength);
63 lastBlockSize = (int)(length % blockLength);
65 if (lastBlockSize > 0)
68 lastBlockSize = blockLength;
71 _lastBlockLength = lastBlockSize;
72 _firstArray =
new T[numBlocks][];
82 get {
return _length; }
85 public int BlockLength {
86 get {
return _blockLength; }
90 get {
return Length; }
94 throw new NotImplementedException();
98 throw new NotImplementedException();
101 public T
this[
long index] {
103 var block = _firstArray[index / _blockLength];
105 return _defaultValue;
107 return block[index % _blockLength];
110 long blockIndex = index / _blockLength;
112 var block = _firstArray[blockIndex];
114 if (_comparer.Equals(value, _defaultValue))
117 if (blockIndex == _firstArray.Length - 1)
118 block =
new T[_lastBlockLength];
120 block =
new T[_blockLength];
122 if (!_comparer.Equals(
default(T), _defaultValue))
123 for (
int i = 0; i < block.Length; i++)
124 block[i] = _defaultValue;
126 _firstArray[blockIndex] = block;
129 block[index % _blockLength] = value;
135 throw new ArgumentOutOfRangeException(
"newLength",
"newLength can't be negative.");
137 if (newLength == 0) {
138 _firstArray = _emptyArray;
139 _lastBlockLength = 0;
147 numBlocks = (int)(newLength / _blockLength);
148 lastBlockSize = (int)(newLength % _blockLength);
150 if (lastBlockSize > 0)
153 lastBlockSize = _blockLength;
156 _lastBlockLength = lastBlockSize;
158 T[][] newArray = _firstArray;
159 if (numBlocks != _firstArray.Length) {
160 int minBlocks =
System.Math.Min(numBlocks, _firstArray.Length);
161 newArray =
new T[numBlocks][];
162 for (
int i = 0; i < minBlocks; i++)
163 newArray[i] = _firstArray[i];
166 var block = newArray[numBlocks - 1];
168 int oldLength = block.Length;
169 Array.Resize(ref block, _lastBlockLength);
170 newArray[numBlocks - 1] = block;
172 if (!_comparer.Equals(
default(T), _defaultValue))
173 for (
int i = oldLength; i < _lastBlockLength; i++)
174 block[i] = _defaultValue;
177 if (_firstArray.Length > 0 && newLength > _length && newArray.Length != _firstArray.Length) {
178 int oldLastBlockIndex = _firstArray.Length - 1;
179 if (newArray[oldLastBlockIndex] != null)
180 Array.Resize(ref newArray[oldLastBlockIndex], _blockLength);
183 _firstArray = newArray;
187 void ICollection<T>.Add(T item) {
188 throw new NotImplementedException();
191 void ICollection<T>.Clear() {
192 throw new NotImplementedException();
196 return IndexOf(item) != -1;
199 void ICollection<T>.CopyTo(T[] array,
int arrayIndex) {
200 throw new NotImplementedException();
203 bool ICollection<T>.Remove(T item) {
204 throw new NotSupportedException();
207 int ICollection<T>.Count {
208 get {
return (
int) Length; }
211 bool ICollection<T>.IsReadOnly {
212 get {
return false; }
215 public bool Contains(T item,
long startIndex,
long count) {
216 return IndexOf(item, startIndex, count) != -1;
220 return IndexOf(item, 0, _length);
223 void IList<T>.Insert(
int index, T item) {
224 throw new NotImplementedException();
227 void IList<T>.RemoveAt(
int index) {
228 throw new NotImplementedException();
231 T IList<T>.this[
int index] {
232 get {
return this[index]; }
233 set {
this[index] = value; }
236 int IList<T>.IndexOf(T item) {
237 return (
int) IndexOf(item);
240 public long IndexOf(T item,
long startIndex,
long count) {
241 if (startIndex < 0 || startIndex > _length)
242 throw new ArgumentOutOfRangeException(
"startIndex");
247 long end = startIndex + count;
248 if (count < 0 || end > _length)
249 throw new ArgumentOutOfRangeException(
"count");
251 long blockIndex = startIndex / _blockLength;
252 long positionInBlock = startIndex % _blockLength;
253 T[] block = _firstArray[blockIndex];
254 long position = startIndex;
258 position += _blockLength - positionInBlock;
265 block = _firstArray[blockIndex];
269 if (_comparer.Equals(block[positionInBlock], item))
277 if (positionInBlock > block.Length) {
280 block = _firstArray[blockIndex];
286 return _BinarySearch(item, 0, _length, Comparer<T>.Default.Compare);
290 if (comparer == null)
291 comparer = Comparer<T>.Default.Compare;
293 return _BinarySearch(item, 0, _length, comparer);
296 public long BinarySearch(T item,
long startIndex,
long count, Comparison<T> comparer = null) {
297 if (startIndex < 0 || startIndex > _length)
298 throw new ArgumentOutOfRangeException(
"startIndex");
303 long end = startIndex + count;
304 if (count < 0 || end > _length)
305 throw new ArgumentOutOfRangeException(
"count");
307 if (comparer == null)
308 comparer = Comparer<T>.Default.Compare;
310 return _BinarySearch(item, startIndex, count, comparer);
313 private long _BinarySearch(T item,
long startIndex,
long count, Comparison<T> comparer) {
318 long middle = count / 2;
319 long position = startIndex + middle;
320 int comparison = comparer(item,
this[position]);
324 if (comparison < 0) {
328 startIndex += middle;
334 public void Sort(Comparison<T> comparer = null) {
335 if (comparer == null)
336 comparer = Comparer<T>.Default.Compare;
340 _Sort(parallelSort, 0, _length, comparer);
345 public void Sort(
long startIndex,
long count, Comparison<T> comparer) {
346 if (startIndex < 0 || startIndex > _length)
347 throw new ArgumentOutOfRangeException(
"startIndex");
352 long end = startIndex + count;
353 if (count < 0 || end > _length)
354 throw new ArgumentOutOfRangeException(
"count");
356 if (comparer == null)
357 comparer = Comparer<T>.Default.Compare;
361 _Sort(parallelSort, startIndex, count, comparer);
370 long pivotOffset = _Partition(startIndex, count, comparer);
373 if (parallelSort == null || count < 10000)
374 _Sort(parallelSort, startIndex, pivotOffset, comparer);
382 if (parallelCount >= Environment.ProcessorCount) {
388 _Sort(parallelSort, startIndex, pivotOffset, comparer);
390 bool shouldProcessNormally =
false;
396 ThreadPool.QueueUserWorkItem
402 _Sort(parallelSort, startIndex, pivotOffset, comparer);
403 }
catch (Exception exception) {
405 lock (parallelSort) {
407 if (exceptions == null) {
408 exceptions =
new List<Exception>();
412 exceptions.Add(exception);
419 int parallelRemaining = Interlocked.Decrement(ref parallelSort.
ExecutingCount);
423 if (parallelRemaining == 0)
425 Monitor.Pulse(parallelSort);
435 shouldProcessNormally =
true;
438 if (shouldProcessNormally)
439 _Sort(parallelSort, startIndex, pivotOffset, comparer);
443 _Sort(parallelSort, startIndex + pivotOffset + 1, count - pivotOffset - 1, comparer);
445 private long _Partition(
long startIndex,
long count, Comparison<T> comparer) {
446 long pivotIndex = startIndex + count / 2;
447 T pivotValue =
this[pivotIndex];
449 long right = startIndex + count - 1;
450 if (pivotIndex != right)
451 this[pivotIndex] =
this[right];
453 long storeIndex = startIndex;
454 for (
long index = startIndex; index < right; index++) {
455 T valueAtIndex =
this[index];
456 if (comparer(valueAtIndex, pivotValue) >= 0)
459 if (index != storeIndex) {
460 this[index] =
this[storeIndex];
461 this[storeIndex] = valueAtIndex;
467 if (right != storeIndex)
468 this[right] =
this[storeIndex];
470 this[storeIndex] = pivotValue;
472 return storeIndex - startIndex;
475 public void Swap(
long position1,
long position2) {
476 if (position1 < 0 || position1 >= _length)
477 throw new ArgumentOutOfRangeException(
"position1");
479 if (position2 < 0 || position2 >= _length)
480 throw new ArgumentOutOfRangeException(
"position2");
482 if (position1 == position2)
485 T value1 =
this[position1];
486 this[position1] =
this[position2];
487 this[position2] = value1;
491 int lastBlockIndex = _firstArray.Length - 1;
492 for (
int i = 0; i <= lastBlockIndex; i++) {
493 var block = _firstArray[i];
497 if (i == lastBlockIndex)
498 numberOfFakes = _lastBlockLength;
500 numberOfFakes = _blockLength;
502 for (
int j = 0; j < numberOfFakes; j++)
503 yield
return _defaultValue;
505 foreach (var value
in block)
511 #region BigArrayParallelSort
520 while (ExecutingCount > 0)
524 if (Exceptions != null)
531 IEnumerator IEnumerable.GetEnumerator() {
532 return GetEnumerator();
bool Contains(T item, long startIndex, long count)
void Insert(long index, T item)
long _Partition(long startIndex, long count, Comparison< T > comparer)
long IndexOf(T item, long startIndex, long count)
readonly int _blockLength
BigArray(long length, T defaultValue, int blockLength)
void RemoveAt(long index)
List< Exception > Exceptions
long BinarySearch(T item, Comparison< T > comparer)
long BinarySearch(T item, long startIndex, long count, Comparison< T > comparer=null)
void Sort(long startIndex, long count, Comparison< T > comparer)
IEnumerator< T > GetEnumerator()
BigArray(long length, int blockLength)
void Resize(long newLength)
void _Sort(BigArrayParallelSort parallelSort, long startIndex, long count, Comparison< T > comparer)
void Sort(Comparison< T > comparer=null)
static int ParallelSortCount
long BinarySearch(T item)
void Swap(long position1, long position2)
BigArray(long length, T defaultValue)
long _BinarySearch(T item, long startIndex, long count, Comparison< T > comparer)