public void or(BitmapValue other) {
        switch (other.bitmapType) {
            case EMPTY:
                break;
            case SINGLE_VALUE:
                add(other.singleValue);
                break;
            case BITMAP_VALUE:
                switch (this.bitmapType) {
                    case EMPTY:
                        this.bitmap = new Roaring64Map();
                        this.bitmap.or(other.bitmap);
                        this.bitmapType = BITMAP_VALUE;
                        break;
                    case SINGLE_VALUE:
                        this.bitmap = new Roaring64Map();
                        this.bitmap.or(other.bitmap);
                        this.bitmap.add(this.singleValue);
                        this.bitmapType = BITMAP_VALUE;
                        break;
                    case BITMAP_VALUE:
                        this.bitmap.or(other.bitmap);
                        break;
                    case SET_VALUE: {
                        this.bitmap = new Roaring64Map();
                        this.bitmap.or(other.bitmap);
                        for (Long v : this.set) {
                            this.bitmap.add(v);
                        }
                        this.bitmapType = BITMAP_VALUE;
                        this.set = null;
                        break;
                    }
                }
                break;
            case SET_VALUE:
                switch (this.bitmapType) {
                    case EMPTY: {
                        this.set = new HashSet<>();
                        this.set.addAll(other.set);
                        this.bitmapType = SET_VALUE;
                        break;
                    }
                    case SINGLE_VALUE: {
                        this.set = new HashSet<>(other.set);
                        if (other.set.size() < 32) {
                            this.set.add(singleValue);
                            this.bitmapType = SET_VALUE;
                        } else {
                            fromSetToBitmap();
                            this.bitmap.add(singleValue);
                        }
                        break;
                    }
                    case SET_VALUE: {
                        for (Long v : other.set) {
                            add(v);
                        }
                        break;
                    }
                    case BITMAP_VALUE: {
                        for (Long v : other.set) {
                            bitmap.add(v);
                        }
                        break;
                    }
                }
                break;
        }
    }
@Test
    public void testBitmapValueOr() throws IOException {
        // empty or empty
        BitmapValue bitmap = new BitmapValue(emptyBitmap);
        bitmap.or(emptyBitmap);
        checkBitmap(bitmap, BitmapValue.EMPTY, 0, 0);

        // empty or single
        bitmap = new BitmapValue(emptyBitmap);
        bitmap.or(singleBitmap);
        checkBitmap(bitmap, BitmapValue.SINGLE_VALUE, 1, 2);

        // empty or set
        bitmap = new BitmapValue(emptyBitmap);
        bitmap.or(mediumBitmap);
        checkBitmap(bitmap, BitmapValue.SET_VALUE, 0, 10);

        // empty or bitmap
        bitmap = new BitmapValue(emptyBitmap);
        bitmap.or(largeBitmap);
        checkBitmap(bitmap, BitmapValue.BITMAP_VALUE, 0, 40);

        // single or empty
        bitmap = new BitmapValue(singleBitmap);
        bitmap.or(emptyBitmap);
        checkBitmap(bitmap, BitmapValue.SINGLE_VALUE, 1, 2);

        // single or single (equal)
        bitmap = new BitmapValue(singleBitmap);
        bitmap.or(singleBitmap);
        checkBitmap(bitmap, BitmapValue.SINGLE_VALUE, 1, 2);

        // single or single (not equal)
        bitmap = new BitmapValue(singleBitmap);
        bitmap.or(new BitmapValue(2));
        checkBitmap(bitmap, BitmapValue.SET_VALUE, 1, 3);

        // single or bitmap
        bitmap = new BitmapValue(singleBitmap);
        bitmap.or(new BitmapValue(10, 70));
        checkBitmap(bitmap, BitmapValue.BITMAP_VALUE, 1, 2, 10, 70);

        // single or set (->set)
        bitmap = new BitmapValue(singleBitmap);
        bitmap.or(new BitmapValue(10, 20));
        checkBitmap(bitmap, BitmapValue.SET_VALUE, 1, 2, 10, 20);

        // single or set (->bitmap)
        bitmap = new BitmapValue(singleBitmap);
        bitmap.or(new BitmapValue(10, 42));
        checkBitmap(bitmap, BitmapValue.BITMAP_VALUE, 1, 2, 10, 42);

        // single or set (->set)
        bitmap = new BitmapValue(singleBitmap);
        bitmap.or(new BitmapValue(5, 10));
        checkBitmap(bitmap, BitmapValue.SET_VALUE, 1, 2, 5, 10);

        // bitmap or empty
        bitmap = new BitmapValue(largeBitmap);
        bitmap.or(emptyBitmap);
        checkBitmap(bitmap, BitmapValue.BITMAP_VALUE, 0, 40);

        // bitmap or single
        bitmap = new BitmapValue(largeBitmap);
        bitmap.or(new BitmapValue(100));
        checkBitmap(bitmap, BitmapValue.BITMAP_VALUE, 0, 40, 100, 101);

        // bitmap or bitmap
        bitmap = new BitmapValue(largeBitmap);
        bitmap.or(new BitmapValue(30, 80));
        checkBitmap(bitmap, BitmapValue.BITMAP_VALUE, 0, 80);

        // bitmap or set
        bitmap = new BitmapValue(largeBitmap);
        bitmap.or(new BitmapValue(30, 50));
        checkBitmap(bitmap, BitmapValue.BITMAP_VALUE, 0, 50);

        // set or empty
        bitmap = new BitmapValue(mediumBitmap);
        bitmap.or(emptyBitmap);
        checkBitmap(bitmap, BitmapValue.SET_VALUE, 0, 10);

        // set or single (->map)
        bitmap = new BitmapValue(0, 32);
        bitmap.or(new BitmapValue(32));
        checkBitmap(bitmap, BitmapValue.BITMAP_VALUE, 0, 33);

        // set or single (->set)
        bitmap = new BitmapValue(mediumBitmap);
        bitmap.or(new BitmapValue(10));
        checkBitmap(bitmap, BitmapValue.SET_VALUE, 0, 11);

        // set or bitmap
        bitmap = new BitmapValue(mediumBitmap);
        bitmap.or(new BitmapValue(8, 100));
        checkBitmap(bitmap, BitmapValue.BITMAP_VALUE, 0, 100);

        // set or set
        bitmap = new BitmapValue(mediumBitmap);
        bitmap.or(new BitmapValue(3, 15));
        checkBitmap(bitmap, BitmapValue.SET_VALUE, 0, 15);
    }