/// <summary>Flush the state and update the header</summary>
        /// <returns>Slice contained the finished compressed bitmap</returns>
        /// <remarks>You cannot write any more words after Packing, until <see cref="Reset"/> is called.</remarks>
        public void Pack()
        {
            if (m_packed)
            {
                ThrowAlreadyPacked();
            }

            // flush any pending word
            Flush();

            if (m_words == 0)
            {             // empty!
                m_bounds = BitRange.Empty;
                // there will be no header
                m_writer.Position = m_head;
            }
            else
            {
                // we need to find the lowest and highest bits
                m_bounds = CompressedBitmap.ComputeBounds(m_writer.ToMutableSlice(), m_words);

                // update the header
                int p;
                m_writer.Rewind(out p, m_head);
                //the last word is either a literal, or a 1-bit filler
                m_writer.WriteFixed32(CompressedWord.MakeHeader(m_bounds.Highest));
                m_writer.Position = p;
            }

            m_packed = true;
        }
예제 #2
0
        public CompressedBitmapBuilder(CompressedBitmap bitmap)
        {
            if (bitmap == null)
            {
                throw new ArgumentNullException("bitmap");
            }
            if ((bitmap.Data.Count & 3) != 0)
            {
                throw new ArgumentException("Bitmap's underlying buffer size should be a multiple of 4 bytes", "bitmap");
            }

            if (bitmap.Count == 0)
            {
                m_words = s_emptyArray;
                var range = BitRange.Empty;
                m_lowest  = range.Lowest;
                m_highest = range.Highest;
            }
            else
            {
                m_words = DecodeWords(bitmap.Data, bitmap.Count, bitmap.Bounds);
                m_size  = bitmap.Count;

                var bounds = bitmap.Bounds;
                m_lowest  = bounds.Lowest;
                m_highest = bounds.Highest;
            }
        }
예제 #3
0
 public CompressedBitmapBitView(CompressedBitmap bitmap)
 {
     if (bitmap == null)
     {
         throw new ArgumentNullException("bitmap");
     }
     m_bitmap = bitmap;
 }
예제 #4
0
        /// <summary>Performs a logical NAND between two compressed bitmaps</summary>
        /// <param name="left">First compressed bitmap</param>
        /// <param name="right">Second compressed bitmap</param>
        /// <returns>Compressed slice with the result of boolean expression <paramref name="left"/> AND NOT(<paramref name="right"/>)</returns>
        public static CompressedBitmap AndNot(this CompressedBitmap left, CompressedBitmap right)
        {
            if (left == null)
            {
                throw new ArgumentNullException(nameof(left));
            }
            if (right == null)
            {
                throw new ArgumentNullException(nameof(right));
            }

            if (left.Count == 0 || right.Count == 0)
            {
                return(CompressedBitmap.Empty);
            }
            return(CompressedBinaryExpression(left, right, LogicalOperation.AndNot));
        }
예제 #5
0
        public static CompressedBitmap And([NotNull] this CompressedBitmap left, [NotNull] CompressedBitmap right)
        {
            if (left == null)
            {
                throw new ArgumentNullException("left");
            }
            if (right == null)
            {
                throw new ArgumentNullException("right");
            }

            if (left.Count == 0 || right.Count == 0)
            {
                return(CompressedBitmap.Empty);
            }
            return(CompressedBinaryExpression(left, right, LogicalOperation.And));
        }
예제 #6
0
        /// <summary>Returns a list of ids matching a specific value</summary>
        /// <param name="trans"></param>
        /// <param name="value">Value to lookup</param>
        /// <param name="reverse"></param>
        /// <returns>List of document ids matching this value for this particular index (can be empty if no document matches)</returns>
        public async Task <IEnumerable <long> > LookupAsync([NotNull] IFdbReadOnlyTransaction trans, TValue value, bool reverse = false)
        {
            var key  = this.Location.Keys.Encode(value);
            var data = await trans.GetAsync(key).ConfigureAwait(false);

            if (data.IsNull)
            {
                return(null);
            }
            if (data.IsEmpty)
            {
                return(Enumerable.Empty <long>());
            }
            var bitmap = new CompressedBitmap(data);

            if (reverse)
            {
                throw new NotImplementedException();                      //TODO: GetView(reverse:true) !
            }
            return(bitmap.GetView().Select(x => (long)x /*BUGBUG 64 bits*/));
        }
예제 #7
0
        public static CompressedBitmap XorNot([NotNull] this CompressedBitmap left, [NotNull] CompressedBitmap right)
        {
            if (left == null)
            {
                throw new ArgumentNullException(nameof(left));
            }
            if (right == null)
            {
                throw new ArgumentNullException(nameof(right));
            }

            if (left.Count == 0)
            {
                return(right.Count == 0 ? CompressedBitmap.Empty : right);
            }
            if (right.Count == 0)
            {
                return(left);
            }
            return(CompressedBinaryExpression(left, right, LogicalOperation.XorNot));
        }
예제 #8
0
        /// <summary>Performs a logical NOT on a compressed bitmaps</summary>
        /// <param name="bitmap">Compressed bitmap</param>
        /// <param name="size">Minimum logical size of the result (bits in the uncompressed bitmap)</param>
        /// <returns>Compressed slice with the result of flipping all the bits in <paramref name="bitmap"/>, containing up to at least <paramref name="size"/> bits.</returns>
        /// <remarks>If <paramref name="bitmap"/> is larger than <paramref name="size"/>, then the resulting bitmap will be larger.</remarks>
        public static CompressedBitmap Not(this CompressedBitmap bitmap, int size)
        {
            if (bitmap == null)
            {
                throw new ArgumentNullException(nameof(bitmap));
            }

            // there is a high change that the final bitmap will have the same size, with an optional extra filler word at the end
            var writer = new CompressedBitmapWriter(bitmap.Count + 1);
            int n      = 0;

            if (bitmap.Count > 0)
            {
                foreach (var word in bitmap)
                {
                    if (word.IsLiteral)
                    {
                        writer.Write(CompressedWord.MakeLiteral((uint)(~word.Literal)));
                        n += 31;
                    }
                    else
                    {
                        int fc = word.FillCount;
                        writer.Write(word.FillBit == 1 ? CompressedWord.ALL_ZEROES : CompressedWord.ALL_ONES, fc);
                        n += 31 * fc;
                    }
                }
            }
            if (n < size)
            {
                writer.Write(CompressedWord.ALL_ONES, size / 31);
                int r = size % 31;
                if (r > 0)
                {
                    writer.Write((1u << r) - 1);
                }
            }
            return(writer.GetBitmap());
        }
예제 #9
0
        /// <summary>Performs a binary operation between two compressed bitmaps</summary>
        /// <param name="left">First compressed bitmap</param>
        /// <param name="right">Second compressed bitmap</param>
        /// <param name="op">Type of operation to perform (And, Or, Xor, ...)</param>
        /// <returns>Compressed slice with the result of boolean expression <paramref name="left"/> AND <paramref name="right"/></returns>
        internal static CompressedBitmap CompressedBinaryExpression(CompressedBitmap left, CompressedBitmap right, LogicalOperation op)
        {
            Contract.Requires(left != null && right != null && /*op != LogicalOperation.And &&*/ Enum.IsDefined(typeof(LogicalOperation), op));

            var writer = new CompressedBitmapWriter();

            using (var liter = left.GetEnumerator())
                using (var riter = right.GetEnumerator())
                {
                    int ln = 0;             // remaining count of current word in left
                    int rn = 0;             // remaining count of current word in right

                    uint lw = 0;            // value of current word in left (if ln > 0)
                    uint rw = 0;            // value of current word in right (if rn > 0)

                    const int DONE = -1;

                    while (true)
                    {
                        if (ln == 0)
                        {
                            if (!liter.MoveNext())
                            {                     // left is done
                                if (op == LogicalOperation.And || rn == DONE)
                                {                 // no need to continue
                                    break;
                                }
                                // continue with right until it's done
                                ln = DONE;
                                lw = 0;
                                continue;
                            }
                            ln = liter.Current.WordCount;
                            lw = liter.Current.WordValue;
                        }
                        if (rn == 0)
                        {
                            if (!riter.MoveNext())
                            {                     // right is done
                                if (op == LogicalOperation.And || ln == DONE)
                                {                 // no need to continue
                                    break;
                                }
                                // continue with left until it's done
                                rn = DONE;
                                rw = 0;
                                continue;
                            }
                            rn = riter.Current.WordCount;
                            rw = riter.Current.WordValue;
                        }

                        if (ln == DONE)
                        {                 // copy right
                            writer.Write((uint)rw, rn);
                            rn = 0;
                        }
                        else if (rn == DONE)
                        {                 // copy left
                            writer.Write((uint)lw, ln);
                            ln = 0;
                        }
                        else
                        {                 // merge left & right
                            int n = Math.Min(ln, rn);
                            switch (op)
                            {
                            case LogicalOperation.And:              writer.Write((uint)(lw & rw), n); break;

                            case LogicalOperation.AndNot:   writer.Write((uint)(lw & (~rw & LITERAL_MASK)), n); break;

                            case LogicalOperation.Or:               writer.Write((uint)(lw | rw), n); break;

                            case LogicalOperation.OrNot:    writer.Write((uint)(lw | (~rw & LITERAL_MASK)), n); break;

                            case LogicalOperation.Xor:              writer.Write((uint)(lw ^ rw), n); break;

                            case LogicalOperation.XorNot:   writer.Write((uint)(lw ^ (~rw & LITERAL_MASK)), n); break;

                            default: throw new InvalidOperationException();
                            }
                            ln -= n;
                            rn -= n;
                        }
                    }
                }

            return(writer.GetBitmap());
        }
 public CompressedBitmapBitView(CompressedBitmap bitmap)
 {
     Contract.NotNull(bitmap);
     m_bitmap = bitmap;
 }