@Override
    public MapTileList computeFromSource(final MapTileList pSource, final MapTileList pReuse) {
        final MapTileList out = pReuse != null ? pReuse : new MapTileList();
        for (int i = 0; i < pSource.getSize(); i++) {
            final long sourceIndex = pSource.get(i);
            final int sourceZoom = MapTileIndex.getZoom(sourceIndex);
            final int destZoom = sourceZoom + mZoomDelta;
            if (destZoom < 0 || destZoom > MapTileIndex.mMaxZoomLevel) {
                continue;
            }
            final int sourceX = MapTileIndex.getX(sourceIndex);
            final int sourceY = MapTileIndex.getY(sourceIndex);
            if (mZoomDelta <= 0) {
                out.put(MapTileIndex.getTileIndex(destZoom, sourceX >> -mZoomDelta, sourceY >> -mZoomDelta));
                continue;
            }
            final int power = 1 << mZoomDelta;
            final int destX = sourceX << mZoomDelta;
            final int destY = sourceY << mZoomDelta;
            for (int j = 0; j < power; j++) {
                for (int k = 0; k < power; k++) {
                    out.put(MapTileIndex.getTileIndex(destZoom, destX + j, destY + k));
                }
            }
        }
        return out;
    }
@Test
    public void testComputeFromSource() {
        final MapTileList source = new MapTileList();
        final MapTileList dest = new MapTileList();
        final HashSet<Long> set = new HashSet<>();
        final int sourceZoom = 5;
        final int sourceXMin = 10;
        final int sourceXMax = 15;
        final int sourceYMin = 20;
        final int sourceYMax = 22;
        final int destMinus1XMin = sourceXMin >> 1;
        final int destMinus1XMax = sourceXMax >> 1;
        final int destMinus1YMin = sourceYMin >> 1;
        final int destMinus1YMax = sourceYMax >> 1;
        final int destPlus1XMin = sourceXMin << 1;
        final int destPlus1XMax = (sourceXMax << 1) + 1;
        final int destPlus1YMin = sourceYMin << 1;
        final int destPlus1YMax = (sourceYMax << 1) + 1;
        for (int i = sourceXMin; i <= sourceXMax; i++) {
            for (int j = sourceYMin; j <= sourceYMax; j++) {
                source.put(MapTileIndex.getTileIndex(sourceZoom, i, j));
            }
        }
        Assert.assertEquals((sourceXMax - sourceXMin + 1) * (sourceYMax - sourceYMin + 1), source.getSize());

        // count checking
        final int minMaxDelta = 4;
        for (int zoomDelta = -minMaxDelta; zoomDelta < minMaxDelta; zoomDelta++) {
            final MapTileListZoomComputer computer = new MapTileListZoomComputer(zoomDelta);
            dest.clear();
            computer.computeFromSource(source, dest);
            final String tag = "zoomDelta=" + zoomDelta;
            if (sourceZoom + zoomDelta < 0 || sourceZoom + zoomDelta > MapTileIndex.mMaxZoomLevel) {
                Assert.assertEquals(tag, 0, dest.getSize());
            } else if (zoomDelta <= 0) {
                Assert.assertEquals(tag, source.getSize(), dest.getSize());
            } else {
                Assert.assertEquals(tag, source.getSize() << (2 * zoomDelta), dest.getSize());
            }
        }

        MapTileListZoomComputer computer;
        // data checking for -1
        computer = new MapTileListZoomComputer(-1);
        dest.clear();
        computer.computeFromSource(source, dest);
        set.clear();
        populateSet(set, dest);
        check(set, sourceZoom + computer.getZoomDelta(), destMinus1XMin, destMinus1XMax, destMinus1YMin, destMinus1YMax);

        // data checking for +1
        computer = new MapTileListZoomComputer(1);
        dest.clear();
        computer.computeFromSource(source, dest);
        set.clear();
        populateSet(set, dest);
        check(set, sourceZoom + computer.getZoomDelta(), destPlus1XMin, destPlus1XMax, destPlus1YMin, destPlus1YMax);
    }