public boolean remove(long member) {
        assert member >= 0;
        int prefix = (int) (member >>> Integer.SIZE);

        if (prefix == lastPrefix) {
            if (lastStorage.remove((int) member)) {
                lastPrefix = -1;
                lastStorage = null;
                return storages.clear(prefix);
            } else {
                return false;
            }
        } else {
            Storage32 storage = storages.get(prefix);
            if (storage == null) {
                return false;
            }
            if (storage.remove((int) member)) {
                lastPrefix = -1;
                lastStorage = null;
                return storages.clear(prefix);
            } else {
                lastPrefix = prefix;
                lastStorage = storage;
                return false;
            }
        }
    }
@Test
    public void testRemove() {
        // try to clear empty set
        for (long i = 0; i < ARRAY_STORAGE_32_MAX_SIZE / 2; ++i) {
            clear(i);
            verify();
        }

        // at the beginning
        for (long i = 0; i < ARRAY_STORAGE_32_MAX_SIZE / 2; ++i) {
            set(i);
        }
        for (long i = 0; i < ARRAY_STORAGE_32_MAX_SIZE / 2 + 100; ++i) {
            clear(i);
            verify();
            // try nonexistent
            clear(i);
            verify();
        }

        // offset
        for (long i = 1000000; i < 1000000 + ARRAY_STORAGE_32_MAX_SIZE; ++i) {
            set(i);
        }
        for (long i = 1000000 + ARRAY_STORAGE_32_MAX_SIZE + 100; i >= 1000000; --i) {
            clear(i);
            verify();
            // try nonexistent
            clear(i);
            verify();
        }

        // test empty again
        for (long i = 111; i < 1111; ++i) {
            clear(i);
            verify();
        }

        // try gaps
        for (long i = 0; i < 1000; ++i) {
            set(i * i);
        }
        for (long i = 0; i < 1000; ++i) {
            clear(i * i);
            verify();
            clear(i * i);
            verify();
        }

        // try larger gaps
        for (long i = (long) Math.sqrt(Long.MAX_VALUE) - 1000; i < (long) Math.sqrt(Long.MAX_VALUE); ++i) {
            set(i * i);
        }
        for (long i = (long) Math.sqrt(Long.MAX_VALUE) - 1000; i < (long) Math.sqrt(Long.MAX_VALUE); ++i) {
            clear(i * i);
            verify();
        }

        // try larger 2-element gaps
        for (long i = (long) Math.sqrt(Long.MAX_VALUE) - 1000; i < (long) Math.sqrt(Long.MAX_VALUE); ++i) {
            set(i * i);
            set(i * i - 1);
        }
        for (long i = (long) Math.sqrt(Long.MAX_VALUE) - 1000; i < (long) Math.sqrt(Long.MAX_VALUE); ++i) {
            clear(i * i);
            verify();
            clear(i * i - 1);
            verify();
        }

        // try some edge cases
        for (long i = 0; i <= 2; ++i) {
            set(i);
        }
        for (long i = 0; i <= 2; ++i) {
            clear(i);
            verify();
        }
        for (long i = Short.MAX_VALUE - 2; i <= Short.MAX_VALUE + 2; ++i) {
            set(i);
        }
        for (long i = Short.MAX_VALUE - 2; i <= Short.MAX_VALUE + 2; ++i) {
            clear(i);
            verify();
        }
        for (long i = Integer.MAX_VALUE - 2; i <= (long) Integer.MAX_VALUE + 2; ++i) {
            set(i);
        }
        for (long i = Integer.MAX_VALUE - 2; i <= (long) Integer.MAX_VALUE + 2; ++i) {
            clear(i);
            verify();
        }
        for (long i = Long.MAX_VALUE; i >= Long.MAX_VALUE - 2; --i) {
            set(i);
        }
        for (long i = Long.MAX_VALUE; i >= Long.MAX_VALUE - 2; --i) {
            clear(i);
            verify();
        }
    }