/*
* Copyright (c) 2011-2015 EPFL DATA Laboratory
* Copyright (c) 2014-2015 The Squall Collaboration (see NOTICE)
*
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ch.epfl.data.squall.thetajoin.adaptive.advisor;
import java.io.Serializable;
import ch.epfl.data.squall.storage.BitVector;
/**
* Utility class to efficiently simulate tuple discards.
*/
public class Discard implements Serializable {
/**
* This method divides the array into k parts and returns the ith part of
* the sorted array. The method operates in place and returns two indices
* (start and end, both inclusive). The array is not sorted after the method
* is called, but the range [start, end] contains the same elements as
* [start, end] in the sorted array. This method operates in expected linear
* time. Worst case time is quadratic if the array is close to sorted (or
* reverse sorted). Works best if the input array is in random order. The
* size of a single part is ceil(arr.length / parts). The last few parts
* might be empty.
*
* @param arr
* The input array.
* @param parts
* The number of parts the array should be divided into.
* @param index
* The index of the required part, should be in [0, parts)
* @return An array containing two indices (start and end), both are
* inclusive. If the required part is empty, the method will return
* {arr.length, arr.length - 1}.
*/
public static int[] keep(int[] arr, int[] addresses, BitVector isTagged,
int parts, int index) {
final int size = (arr.length + parts - 1) / parts;
final int from = index * size;
final int to = Math.min((index + 1) * size - 1, arr.length - 1);
if (from > to)
return new int[] { arr.length, arr.length - 1 };
return keepFrom(arr, addresses, isTagged, from, to, 0, arr.length - 1);
}
protected static int[] keepFrom(int[] arr, int[] addresses,
BitVector isTagged, int from, int to, int i, int j) {
while (true) {
final int p = pivot(arr, addresses, isTagged, i, i, j);
if (from == i)
return new int[] {
i,
keepUntil(arr, addresses, isTagged, to, i,
arr.length - 1) };
if (p < from)
i = p + 1;
else if (p == from)
return new int[] {
p,
keepUntil(arr, addresses, isTagged, to, i,
arr.length - 1) };
else
j = p - 1;
}
}
protected static int keepUntil(int[] arr, int[] addresses,
BitVector isTagged, int to, int i, int j) {
while (true) {
final int p = pivot(arr, addresses, isTagged, i, i, j);
if (p > to)
j = p - 1;
else if (p == to)
return p;
else
i = p + 1;
}
}
protected static int pivot(int[] arr, int[] addresses, BitVector isTagged,
int p, int i, int j) {
final int pV = arr[p];
final boolean pVB = isTagged.get(p);
final int pA = addresses[p];
int temp = arr[j];
boolean tempB = isTagged.get(j);
int tempA = addresses[j];
arr[j] = pV;
isTagged.set(j, pVB);
addresses[j] = pA;
arr[p] = temp;
isTagged.set(p, tempB);
addresses[p] = tempA;
int ind = i;
for (int k = i; k < j; ++k)
if (arr[k] < pV) {
temp = arr[k];
tempB = isTagged.get(k);
tempA = addresses[k];
arr[k] = arr[ind];
isTagged.set(k, isTagged.get(ind));
addresses[k] = addresses[ind];
arr[ind] = temp;
isTagged.set(ind, tempB);
addresses[ind] = tempA;
++ind;
}
temp = arr[ind];
tempB = isTagged.get(ind);
tempA = addresses[ind];
arr[ind] = arr[j];
isTagged.set(ind, isTagged.get(j));
addresses[ind] = addresses[j];
arr[j] = temp;
isTagged.set(j, tempB);
addresses[j] = tempA;
return ind;
}
/**
*
*/
private static final long serialVersionUID = 1L;
}