Exemple #1
0
        /// <summary>
        /// Sets the bits in the region starting at location and having
        /// given width and height
        /// </summary>
        /// <param name="location">Top Left of the the Region</param>
        /// <param name="width">Width of the Region</param>
        /// <param name="height">Height of the Region</param>
        internal void SetRegion(MatrixCell location, int width, int height)
        {
            long targetRow    = location.Row;
            long targetCol    = location.Col;
            int  targetWidth  = width;
            int  targetHeight = height;

            // Interchange Row & Column and width & height if the BitOrientation is Vertical
            if (BitOrientation == Orientation.Vertical)
            {
                targetRow    = location.Col;
                targetCol    = location.Row;
                targetWidth  = height;
                targetHeight = width;
            }

            // Optimization: If the region is only 1 bit wide and high
            if ((targetWidth == 1) && (targetHeight == 1))
            {
                this[targetRow, targetCol] = true;
                return;
            }

            for (var row = 0; row < targetHeight; row++)
            {
                for (var col = 0; col < targetWidth; col++)
                {
                    this[targetRow + row, targetCol + col] = true;
                }
            }
        }
Exemple #2
0
        /// <summary>
        /// Sets the bits in the region starting at location and having
        /// given width and height
        /// </summary>
        /// <param name="location">Top Left of the the Region</param>
        /// <param name="width">Width of the Region</param>
        /// <param name="height">Height of the Region</param>
        internal void SetRegion(MatrixCell location, int width, int height)
        {
            if (BitOrientation == Orientation.Horizontal)
            {
                // Optimization: If the region is only 1 bit wide and high
                if ((width == 1) && (height == 1))
                {
                    this[location.Row, location.Col] = true;
                    return;
                }

                for (var row = 0; row < height; row++)
                {
                    for (var col = 0; col < width; col++)
                    {
                        this[location.Row + row, location.Col + col] = true;
                    }
                }
            }
            // Interchange Row & Column and width & height if the BitOrientation is Vertical
            else
            {
                // Optimization: If the region is only 1 bit wide and high
                if ((width == 1) && (height == 1))
                {
                    this[location.Col, location.Row] = true;
                    return;
                }

                for (var row = 0; row < width; row++)
                {
                    for (var col = 0; col < height; col++)
                    {
                        this[location.Col + row, location.Row + col] = true;
                    }
                }
            }
        }
Exemple #3
0
        /// <summary>
        /// Finds the next empty region of given width and height starting
        /// from the startIndex row
        /// </summary>
        /// <param name="startIndex">The row to start the search from</param>
        /// <param name="width">Width of the Region</param>
        /// <param name="height">Height of the Region</param>
        /// <returns></returns>
        internal MatrixCell FindRegion(long startIndex, int width, int height)
        {
            // Swap width and height if the BitOrientation is Vertical
            if ((BitOrientation == Orientation.Vertical) && (width != height))
            {
                var temp = width;
                width  = height;
                height = temp;
            }

            var invalidCell = new MatrixCell(-1, -1);

            if (startIndex < 0 || startIndex >= _rowsInternal)
            {
                throw new ArgumentOutOfRangeException(nameof(startIndex));
            }

            if (startIndex + (height - 1) >= _rowsInternal)
            {
                throw new ArgumentOutOfRangeException(nameof(width), $"Cannot fit item having height of {height} rows in {_rowsInternal - startIndex} rows!");
            }

            if ((width < 1) || (width > 60))
            {
                throw new ArgumentOutOfRangeException(nameof(width), $"Length of the item must be in the range 1 - {MaxBitsPerItem}!");
            }

            if (width > _columnsInternal)
            {
                throw new ArgumentOutOfRangeException(nameof(width), $"Length cannot be greater than number of columns in the BitMatrix!");
            }

            // Optimization: If both width and height are 1 then use a faster
            // loop to find the next empty bit
            if ((width == 1) && (height == 1))
            {
                for (var row = startIndex; row < _rowsInternal; row++)
                {
                    for (var col = 0; col < _columnsInternal; col++)
                    {
                        if (!this[row, col])
                        {
                            // Swap the row and col values if the BitOrientation is Vertical
                            return((BitOrientation == Orientation.Horizontal) ? new MatrixCell(row, col) : new MatrixCell(col, row));
                        }
                    }
                }

                // If the code has reached here it means that it did not find any unset
                // bit in the entire _data. Simply return from here.
                return(invalidCell);
            }

            var mask = (((UInt64)1) << width) - 1;

            for (var row = startIndex; row < _rowsInternal; row++)
            {
                // Quickcheck: If the row is empty then no need to check individual bits in the row
                if (!RowHasData(row))
                {
                    // Current column has no bits set. Check the bits in the next (height - 1)
                    // rows starting at the same column position (0) to check if they are unset
                    if (!AnyBitsSetInRegion(row, 0, width, height))
                    {
                        // Swap the row and col values if the BitOrientation is Vertical
                        return((BitOrientation == Orientation.Horizontal) ? new MatrixCell(row, 0) : new MatrixCell(0, row));
                    }
                }

                // Row is not empty and has some set bits.  Check if there are
                // 'width' continuous unset bits in the column.
                // 1. Check the first 'width' bits
                var rowData = (UInt64)0;
                var col     = 0;
                for (; col < width; col++)
                {
                    rowData <<= 1;
                    rowData  |= this[row, col] ? (UInt64)1 : (UInt64)0;
                }
                if ((rowData & mask) == 0)
                {
                    // Current column has 'width' unset bits starting from 0 position.
                    // Check the bits in the next (height - 1) rows starting at the same
                    // column position (0) to check if they are unset
                    if (!AnyBitsSetInRegion(row, 0, width, height))
                    {
                        // Swap the row and col values if the BitOrientation is Vertical
                        return((BitOrientation == Orientation.Horizontal) ? new MatrixCell(row, 0) : new MatrixCell(0, row));
                    }
                }

                // Shift the rowData by 1 bit and clear the (width + 1)th most significant bit.
                // This way a set of 'width' continuous bits is matched against the mask
                // to check if all the bits are zero.
                var colBegin = 0;
                while (col < _columnsInternal)
                {
                    rowData <<= 1;
                    rowData  &= mask;
                    rowData  |= this[row, col++] ? (UInt64)1 : (UInt64)0;
                    colBegin++;

                    if ((rowData & mask) != 0)
                    {
                        continue;
                    }

                    // Current column has 'width' unset bits starting from colBegin position.
                    // Check the bits in the next (height - 1) rows starting at the same
                    // column position (colBegin) to check if they are unset
                    if (AnyBitsSetInRegion(row, colBegin, width, height))
                    {
                        continue;
                    }

                    // Swap the row and col values if the BitOrientation is Vertical
                    return((BitOrientation == Orientation.Horizontal) ? new MatrixCell(row, colBegin) : new MatrixCell(colBegin, row));
                }
            }

            return(invalidCell);
        }
Exemple #4
0
        /// <summary>
        /// Tries to find an empty region of given width and height starting
        /// from the startIndex row.
        /// </summary>
        /// <param name="startIndex">The row to start the search from</param>
        /// <param name="width">Width of the Region</param>
        /// <param name="height">Height of the Region</param>
        /// <param name="cell">The cell location</param>
        /// <returns>true if successful otherwise false</returns>
        internal bool TryFindRegion(long startIndex, int width, int height, out MatrixCell cell)
        {
            cell = MatrixCell.InvalidCell();

            // Swap width and height if the BitOrientation is Vertical
            if ((BitOrientation == Orientation.Vertical) && (width != height))
            {
                var temp = width;
                width  = height;
                height = temp;
            }

            if ((startIndex < 0 || startIndex >= _rowsInternal) ||
                (startIndex + (height - 1) >= _rowsInternal) ||
                ((width < 1) || (width > MaxBitsPerItem)) ||
                (width > _columnsInternal))
            {
                return(false);
            }

            // Optimization: If both width and height are 1 then use a faster
            // loop to find the next empty cell
            if ((width == 1) && (height == 1))
            {
                for (var row = startIndex; row < _rowsInternal; row++)
                {
                    for (var col = 0; col < _columnsInternal; col++)
                    {
                        // Is the cell unset?
                        if (this[row, col])
                        {
                            continue;
                        }

                        // Swap the row and col values if the BitOrientation is Vertical
                        cell = (BitOrientation == Orientation.Horizontal) ? new MatrixCell(row, col) : new MatrixCell(col, row);
                        return(true);
                    }
                }

                // If the code has reached here it means that it did not find any unset
                // bit in the entire matrix. Return false from here.
                return(false);
            }

            var mask = (((UInt64)1) << width) - 1;

            for (var row = startIndex; row < (_rowsInternal - height + 1); row++)
            {
                // Quickcheck: If the row is empty then no need to check individual bits in the row
                if (!RowHasData(row))
                {
                    // Current column has no bits set. Check the bits in the next (height - 1)
                    // rows starting at the same column position (0) to check if they are unset
                    if (!AnyBitsSetInRegion(row, 0, width, height))
                    {
                        // Swap the row and col values if the BitOrientation is Vertical
                        cell = (BitOrientation == Orientation.Horizontal) ? new MatrixCell(row, 0) : new MatrixCell(0, row);
                        return(true);
                    }
                }

                // Row is not empty and has some set bits.  Check if there are
                // 'width' continuous unset bits in the column.
                // 1. Check the first 'width' bits
                var rowData = 0UL;
                var col     = 0;
                for (; col < width; col++)
                {
                    rowData <<= 1;
                    rowData  |= this[row, col] ? 1UL : 0UL;
                }
                if ((rowData & mask) == 0)
                {
                    // Current column has 'width' unset bits starting from 0 position.
                    // Check the bits in the next (height - 1) rows starting at the same
                    // column position (0) to check if they are unset
                    if (!AnyBitsSetInRegion(row, 0, width, height))
                    {
                        // Swap the row and col values if the BitOrientation is Vertical
                        cell = (BitOrientation == Orientation.Horizontal) ? new MatrixCell(row, 0) : new MatrixCell(0, row);
                        return(true);
                    }
                }

                // Shift the rowData by 1 bit and clear the (width + 1)th most significant bit.
                // This way a set of 'width' continuous bits is matched against the mask
                // to check if all the bits are zero.
                var colBegin = 0;
                while (col < _columnsInternal)
                {
                    rowData <<= 1;
                    rowData  &= mask;
                    rowData  |= this[row, col++] ? 1UL : 0UL;
                    colBegin++;

                    if ((rowData & mask) != 0)
                    {
                        continue;
                    }

                    // Current column has 'width' unset bits starting from colBegin position.
                    // Check the bits in the next (height - 1) rows starting at the same
                    // column position (colBegin) to check if they are unset
                    if (AnyBitsSetInRegion(row, colBegin, width, height))
                    {
                        continue;
                    }

                    // Swap the row and col values if the BitOrientation is Vertical
                    cell = (BitOrientation == Orientation.Horizontal) ? new MatrixCell(row, colBegin) : new MatrixCell(colBegin, row);
                    return(true);
                }
            }

            return(false);
        }