public SegmentIntArrayIndexer(SegmentIntArray array) { _array = array; _currentSegment = 0; _currentBit = 0; if (_array._segType.Length > 0) { _currentIndex = 0; _currentType = _array._segType[0]; _nextIndex = _array._segLength[0]; } else { // Handle the edge case where we have a completely empty array. _currentIndex = _array.Length; _currentType = 0; _nextIndex = _currentIndex; } }
/// <summary> /// Finds the most space efficient representation of the feature /// (with slight slack cut for dense features). The behavior of /// this method depends upon the static value <see cref="CompatibilityLevel"/>. /// </summary> /// <param name="workarray">Should be non-null if you want it to /// consider segment arrays.</param> /// <returns>Returns a more space efficient version of the array, /// or the item itself if that is impossible, somehow.</returns> public IntArray Compress(uint[] workarray = null) { int maxval = 0; int zerocount = 0; int runs = 0; int last = -1; int overflows = 0; int zoverflows = 0; int runnow = 0; // The longest run of having the same value. int len = Length; IIntArrayForwardIndexer ind = GetIndexer(); for (int i = 0; i < len; ++i) { int val = ind[i]; if (workarray != null) { workarray[i] = (uint)val; } if (val == 0) { zerocount++; } else if (val > maxval) { maxval = val; } if (last == val) { runs++; if (++runnow > byte.MaxValue) { // We have 256 items in a row the same. overflows++; if (val == 0) { zoverflows++; } runnow = 0; } } last = val; } // Estimate the costs of the available options. IntArrayBits classicBits = IntArray.NumBitsNeeded(maxval + 1); long denseBits = (long)classicBits * (long)Length; long sparseBits = (long)(Math.Max((int)classicBits, 8) + 8) * (long)(Length - zerocount + zoverflows); long rleBits = (long)(classicBits + 8) * (long)(Length - runs + overflows); long segBits = long.MaxValue; int segTransitions = 0; if (workarray != null) { int bits = SegmentIntArray.BitsForValue((uint)maxval); if (bits <= 21) { SegmentIntArray.SegmentFindOptimalPath(workarray, Length, bits, out segBits, out segTransitions); } } if ((IntArray.CompatibilityLevel & 0x4) == 0) { rleBits = long.MaxValue; } long bestCost = Math.Min(Math.Min(Math.Min(denseBits, sparseBits), rleBits), segBits); IntArrayType bestType = IntArrayType.Dense; if (bestCost >= denseBits * 98 / 100) { // Cut the dense bits a wee bit of slack. } else if (bestCost == sparseBits) { bestType = IntArrayType.Sparse; } else if (bestCost == rleBits) { bestType = IntArrayType.Repeat; } else { bestType = IntArrayType.Segmented; } if (bestType == Type && classicBits == BitsPerItem) { return(this); } IntArray bins = null; if (bestType != IntArrayType.Segmented) { bins = IntArray.New(Length, bestType, classicBits, this); } else { bins = SegmentIntArray.FromWorkArray(workarray, Length, segBits, segTransitions); } return(bins); }