public RoaringBitmap(ulong[] bits64) { int countOfElems = bits64.Length * 64; int countOfContainers = countOfElems / POWER16 + (countOfElems % POWER16 == 0 ? 0 : 1); containers = new Bitmap[countOfContainers]; for (int i = 0; i < countOfContainers; i++) { //Заполняем контейнер int chankCardinality = 0; BitmapContainer bitmapCont = new BitmapContainer(true); for (int j = 0; j < 1024; j++) { //Если эелементы кончились а контейнер не заполнен, то контейнер дозаполняется нулями ulong num = i * 1024 + j < bits64.Length ? bits64[i * 1024 + j] : 0; for (int k = 0; k < 64; k++) { chankCardinality += (int)(num % 2); bitmapCont.Set(j * 64 + k, num % 2 == 1); num /= 2; } } //Записываем контейнер в массив if (chankCardinality < 4096) { containers[i] = chankCardinality > 0 ? new ArrayContainer(bitmapCont) : new ArrayContainer(); } else { containers[i] = bitmapCont; } } }
/// <summary> /// Создает ArrayContainer по существующему BitmapContainer /// </summary> /// <param name="bitmapCon"></param> public ArrayContainer(BitmapContainer bitmapCon) { arrayContainer = new ushort[bitmapCon.cardinality]; int k = 0; for (int i = 0; i < bitmapCon.bits64.Length; i++) { for (int j = 0; j < 64; j++) { if (bitmapCon.Get(j + i * 64)) { arrayContainer[k++] = ((ushort)(j + i * 64)); } } } cardinality = (ulong)arrayContainer.Length; }
/// <summary> /// Записывает в this пересечение с other /// </summary> /// <param name="other"></param> public override void And(Bitmap other) { if (other is BitmapContainer) { ulong c = 0; BitmapContainer otherBitmap = (BitmapContainer)other; for (int i = 0; i < 1024; i++) { bits64[i] &= otherBitmap.bits64[i]; ulong num = bits64[i]; for (int j = 0; j < 64; j++) { c += num % 2; num /= 2; } } cardinality = c; } if (other is ArrayContainer) { ArrayContainer thisContainer = new ArrayContainer(this); other.And(thisContainer); } }