А что если хранить карту значений, где каждый бит будет означать присутствует ли блок в 64 бит в массиве значений. 64 бита по 0 бит, будут означать отсутствие 64-х блоков по 64 бита. Т.е. упаковка 512 байт в 8 байт. Подобный принцип можно применять и к 64-ём блокам и т.п. По сути это карта значений. С помощью которой можно быстро проверять есть ли значения непосредственно далее (ниже по уровню). Или как таблица виртуальной памяти где номер блока означает его присутствие и адрес. TODO: Compare what is faster to store BitSetsIn16Bits or to calculate it TODO: Avoid int usage (replace to long)
Beispiel #1
0
        public BitString(BitString bits)
        {
            if (bits == null)
            {
                throw new ArgumentNullException(nameof(bits));
            }

            _length = bits._length;
            _array = new long[(_length + 63) / 64];

            _minPositiveWord = bits._minPositiveWord;
            _maxPositiveWord = bits._maxPositiveWord;

            if (_array.Length == 1)
            {
                _array[0] = bits._array[0];
            }
            else
            {
                Array.Copy(bits._array, _array, _array.Length);
            }
        }
Beispiel #2
0
        public int GetLastCommonBitIndex(BitString other)
        {
            if (Length != other.Length)
            {
                throw new ArgumentException("Bit strings must have same size", nameof(other));
            }

            var from = Math.Max(_minPositiveWord, other._minPositiveWord);
            var to = Math.Min(_maxPositiveWord, other._maxPositiveWord);

            var otherArray = other._array;

            for (var i = from; i <= to; i++)
            {
                var v1 = _array[i];
                var v2 = otherArray[i];
                var n = v1 & v2;
                if (n != 0)
                {
                    var bits1 = BitSetsIn16Bits[(int)(n & 0xffffu)];
                    var bits2 = BitSetsIn16Bits[(int)((n >> 16) & 0xffffu)];
                    var bits3 = BitSetsIn16Bits[(int)((n >> 32) & 0xffffu)];
                    var bits4 = BitSetsIn16Bits[(int)((n >> 48) & 0xffffu)];

                    if (bits4.Length > 0)
                        return bits4[bits4.Length - 1] + 48 + (int)i * 64;
                    if (bits3.Length > 0)
                        return bits3[bits3.Length - 1] + 32 + (int)i * 64;
                    if (bits2.Length > 0)
                        return bits2[bits2.Length - 1] + 16 + (int)i * 64;
                    return bits1[bits1.Length - 1] + (int)i * 64;
                }
            }

            return -1;
        }
Beispiel #3
0
        public List<int> GetCommonIndices(BitString other)
        {
            if (Length != other.Length)
            {
                throw new ArgumentException("Bit strings must have same size", nameof(other));
            }

            var from = Math.Max(_minPositiveWord, other._minPositiveWord);
            var to = Math.Min(_maxPositiveWord, other._maxPositiveWord);

            var result = new List<int>();

            var otherArray = other._array;

            for (var i = from; i <= to; i++)
            {
                var v1 = _array[i];
                var v2 = otherArray[i];
                var n = v1 & v2;
                if (n != 0)
                {
                    var bits1 = BitSetsIn16Bits[(int)(n & 0xffffu)];
                    var bits2 = BitSetsIn16Bits[(int)((n >> 16) & 0xffffu)];
                    var bits3 = BitSetsIn16Bits[(int)((n >> 32) & 0xffffu)];
                    var bits4 = BitSetsIn16Bits[(int)((n >> 48) & 0xffffu)];

                    if (bits1.Length > 0)
                        result.Add(bits1[0] + (int)i * 64);
                    else if (bits2.Length > 0)
                        result.Add(bits2[0] + 16 + (int)i * 64);
                    else if (bits3.Length > 0)
                        result.Add(bits3[0] + 32 + (int)i * 64);
                    else
                        result.Add(bits4[0] + 48 + (int)i * 64);
                }
            }

            return result;
        }
Beispiel #4
0
        public int CountCommonBits(BitString other)
        {
            if (Length != other.Length)
            {
                throw new ArgumentException("Bit strings must have same size", nameof(other));
            }

            var from = Math.Max(_minPositiveWord, other._minPositiveWord);
            var to = Math.Min(_maxPositiveWord, other._maxPositiveWord);

            var result = 0;

            var otherArray = other._array;

            for (var i = from; i <= to; i++)
            {
                var v1 = _array[i];
                var v2 = otherArray[i];
                var n = v1 & v2;
                if (n != 0)
                {
                    var bits1 = BitSetsIn16Bits[(int)(n & 0xffffu)];
                    var bits2 = BitSetsIn16Bits[(int)((n >> 16) & 0xffffu)];
                    var bits3 = BitSetsIn16Bits[(int)((n >> 32) & 0xffffu)];
                    var bits4 = BitSetsIn16Bits[(int)((n >> 48) & 0xffffu)];

                    result += bits1.Length + bits2.Length + bits3.Length + bits4.Length;
                }
            }

            return result;
        }
Beispiel #5
0
        public bool HaveCommonBits(BitString other)
        {
            if (Length != other.Length)
            {
                throw new ArgumentException("Bit strings must have same size", nameof(other));
            }

#if DEBUG
            var sw = Stopwatch.StartNew();
#endif

            var from = Math.Max(_minPositiveWord, other._minPositiveWord);
            var to = Math.Min(_maxPositiveWord, other._maxPositiveWord);

            var result = false;

#if DEBUG
            var steps = 0;
#endif
            var otherArray = other._array;

            for (var i = from; i <= to; i++)
            {
#if DEBUG
                steps++;
#endif
                var v1 = _array[i];
                var v2 = otherArray[i];
                if (v1 != 0 && v2 != 0 && ((v1 & v2) != 0))
                {
                    result = true;
                    break;
                }
            }

#if DEBUG
            if (sw.Elapsed.TotalMilliseconds > 0.1)
            {
                ConsoleHelpers.Debug("HCB -> Min: {0}, Max: {1}, Delta: {2}, Steps: {3}, Time: {4}", from, to, to - from, steps, sw.Elapsed.TotalMilliseconds);
            }
#endif

            return result;
        }
Beispiel #6
0
        public BitString Xor(BitString value)
        {
            EnsureArgumentIsValid(value);

            var ints = (_length + 63) / 64;
            for (long i = 0; i < ints; i++)
            {
                _array[i] ^= value._array[i];
                RefreshBordersByWord(i);
            }

            //_version++;
            return this;
        }
Beispiel #7
0
        public BitString Or(BitString value)
        {
#if DEBUG
            var sw = Stopwatch.StartNew();
#endif

            EnsureArgumentIsValid(value);

            var ints = (_length + 63) / 64;
            for (long i = 0; i < ints; i++)
            {
                _array[i] |= value._array[i];
                RefreshBordersByWord(i);
            }

            //_version++;

#if DEBUG
            ConsoleHelpers.Debug("OR -> Len: {0}, Time: {1}", _array.Length, sw.Elapsed.TotalMilliseconds);
#endif

            return this;
        }
Beispiel #8
0
 private void EnsureArgumentIsValid(BitString other)
 {
     if (other == null)
         throw new ArgumentNullException();
     if (other._length != _length)
         throw new ArgumentException();
 }