Example #1
0
            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;
                }
            }
Example #2
0
        /// <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);
        }