use of org.apache.hyracks.api.dataflow.value.IBinaryComparator in project asterixdb by apache.
the class MToNPartitioningMergingConnectorDescriptor method createPartitionCollector.
@Override
public IPartitionCollector createPartitionCollector(IHyracksTaskContext ctx, RecordDescriptor recordDesc, int index, int nProducerPartitions, int nConsumerPartitions) throws HyracksDataException {
IBinaryComparator[] comparators = new IBinaryComparator[comparatorFactories.length];
for (int i = 0; i < comparatorFactories.length; ++i) {
comparators[i] = comparatorFactories[i].createBinaryComparator();
}
INormalizedKeyComputer nmkComputer = nkcFactory == null ? null : nkcFactory.createNormalizedKeyComputer();
IPartitionBatchManager pbm = new NonDeterministicPartitionBatchManager(nProducerPartitions);
IFrameReader sortMergeFrameReader = new SortMergeFrameReader(ctx, nProducerPartitions, nProducerPartitions, sortFields, comparators, nmkComputer, recordDesc, pbm);
BitSet expectedPartitions = new BitSet();
expectedPartitions.set(0, nProducerPartitions);
return new PartitionCollector(ctx, getConnectorId(), index, expectedPartitions, sortMergeFrameReader, pbm);
}
use of org.apache.hyracks.api.dataflow.value.IBinaryComparator in project asterixdb by apache.
the class AObjectDescBinaryComparatorFactory method createBinaryComparator.
@Override
public IBinaryComparator createBinaryComparator() {
return new ABinaryComparator() {
final IBinaryComparator ascComp = AObjectAscBinaryComparatorFactory.INSTANCE.createBinaryComparator();
// INTERVAL
// Interval asc and desc comparator factories are not the inverse of each other.
// Thus, we need to specify the interval desc comparator factory for descending comparisons.
final IBinaryComparator descIntervalComp = AIntervalDescPartialBinaryComparatorFactory.INSTANCE.createBinaryComparator();
@Override
public int compare(byte[] b1, int s1, int l1, byte[] b2, int s2, int l2) throws HyracksDataException {
ATypeTag tag1 = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(b1[s1]);
ATypeTag tag2 = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(b2[s2]);
if (tag1 == ATypeTag.INTERVAL && tag2 == ATypeTag.INTERVAL) {
return descIntervalComp.compare(b1, s1 + 1, l1 - 1, b2, s2 + 1, l2 - 1);
}
return -ascComp.compare(b1, s1, l1, b2, s2, l2);
}
};
}
use of org.apache.hyracks.api.dataflow.value.IBinaryComparator in project asterixdb by apache.
the class SpatialIntersectDescriptor method createEvaluatorFactory.
@Override
public IScalarEvaluatorFactory createEvaluatorFactory(final IScalarEvaluatorFactory[] args) {
return new IScalarEvaluatorFactory() {
private static final long serialVersionUID = 1L;
@Override
public IScalarEvaluator createScalarEvaluator(final IHyracksTaskContext ctx) throws HyracksDataException {
return new IScalarEvaluator() {
private final ArrayBackedValueStorage resultStorage = new ArrayBackedValueStorage();
private final DataOutput out = resultStorage.getDataOutput();
private final IPointable inputArg0 = new VoidPointable();
private final IPointable inputArg1 = new VoidPointable();
private final IScalarEvaluator eval0 = args[0].createScalarEvaluator(ctx);
private final IScalarEvaluator eval1 = args[1].createScalarEvaluator(ctx);
private final IBinaryComparator ascDoubleComp = BinaryComparatorFactoryProvider.DOUBLE_POINTABLE_INSTANCE.createBinaryComparator();
private final SpatialUtils spatialUtils = new SpatialUtils();
private final IntArray pointsOffsets0 = new IntArray();
private final IntArray pointsOffsets1 = new IntArray();
private final DoubleArray trianglesX0 = new DoubleArray();
private final DoubleArray trianglesY0 = new DoubleArray();
private final DoubleArray trianglesX1 = new DoubleArray();
private final DoubleArray trianglesY1 = new DoubleArray();
private final AObjectSerializerDeserializer aBooleanSerDer = AObjectSerializerDeserializer.INSTANCE;
private boolean pointOnLine(double pX, double pY, double startX, double startY, double endX, double endY) throws HyracksDataException {
double crossProduct = SpatialUtils.crossProduct(pY - startY, pX - startX, endY - startY, endX - startX);
if (Math.abs(crossProduct) > SpatialUtils.doubleEpsilon()) {
// crossProduct != 0
return false;
}
double dotProduct = SpatialUtils.dotProduct((pX - startX), (pY - startY), (endX - startX), (endY - startY));
if (dotProduct < 0.0) {
return false;
}
double squaredLengthBA = (endX - startX) * (endX - startX) + (endY - startY) * (endY - startY);
if (dotProduct > squaredLengthBA) {
return false;
}
return true;
}
private boolean pointInPolygon(byte[] bytes0, int offset0, byte[] bytes1, int offset1) throws HyracksDataException {
// ray casting
double pX = ADoubleSerializerDeserializer.getDouble(bytes0, offset0 + APointSerializerDeserializer.getCoordinateOffset(Coordinate.X));
double pY = ADoubleSerializerDeserializer.getDouble(bytes0, offset0 + APointSerializerDeserializer.getCoordinateOffset(Coordinate.Y));
int numOfPoints1 = AInt16SerializerDeserializer.getShort(bytes1, offset1 + APolygonSerializerDeserializer.getNumberOfPointsOffset());
if (numOfPoints1 < 3) {
throw new InvalidDataFormatException(getIdentifier(), ATypeTag.SERIALIZED_POLYGON_TYPE_TAG);
}
int counter = 0;
double xInters;
double x1, x2, y1, y2;
x1 = ADoubleSerializerDeserializer.getDouble(bytes1, offset1 + APolygonSerializerDeserializer.getCoordinateOffset(0, Coordinate.X));
y1 = ADoubleSerializerDeserializer.getDouble(bytes1, offset1 + APolygonSerializerDeserializer.getCoordinateOffset(0, Coordinate.Y));
for (int i = 1; i <= numOfPoints1; i++) {
if (i == numOfPoints1) {
x2 = ADoubleSerializerDeserializer.getDouble(bytes1, offset1 + APolygonSerializerDeserializer.getCoordinateOffset(0, Coordinate.X));
y2 = ADoubleSerializerDeserializer.getDouble(bytes1, offset1 + APolygonSerializerDeserializer.getCoordinateOffset(0, Coordinate.Y));
} else {
x2 = ADoubleSerializerDeserializer.getDouble(bytes1, offset1 + APolygonSerializerDeserializer.getCoordinateOffset(i, Coordinate.X));
y2 = ADoubleSerializerDeserializer.getDouble(bytes1, offset1 + APolygonSerializerDeserializer.getCoordinateOffset(i, Coordinate.Y));
}
if (!pointOnLine(pX, pY, x1, y1, x2, y2)) {
if (pY > Math.min(y1, y2)) {
if (pY <= Math.max(y1, y2)) {
if (pX <= Math.max(x1, x2)) {
if (y1 != y2) {
xInters = (pY - y1) * (x2 - x1) / (y2 - y1) + x1;
if (x1 == x2 || pX <= xInters) {
counter++;
}
}
}
}
}
}
x1 = x2;
y1 = y2;
}
if (counter % 2 == 1) {
return true;
} else {
return false;
}
}
private boolean pointInCircle(byte[] bytes0, int offset0, byte[] bytes1, int offset1) throws HyracksDataException {
double x = ADoubleSerializerDeserializer.getDouble(bytes0, offset0 + APointSerializerDeserializer.getCoordinateOffset(Coordinate.X));
double y = ADoubleSerializerDeserializer.getDouble(bytes0, offset0 + APointSerializerDeserializer.getCoordinateOffset(Coordinate.Y));
double cX = ADoubleSerializerDeserializer.getDouble(bytes1, offset1 + ACircleSerializerDeserializer.getCenterPointCoordinateOffset(Coordinate.X));
double cY = ADoubleSerializerDeserializer.getDouble(bytes1, offset1 + ACircleSerializerDeserializer.getCenterPointCoordinateOffset(Coordinate.Y));
double radius = ADoubleSerializerDeserializer.getDouble(bytes1, offset1 + ACircleSerializerDeserializer.getRadiusOffset());
if ((x - cX) * (x - cX) + (y - cY) * (y - cY) <= (radius * radius)) {
return true;
}
return false;
}
private boolean lineLineIntersection(double startX1, double startY1, double endX1, double endY1, double startX2, double startY2, double endX2, double endY2) {
double A1 = endY1 - startY1;
double B1 = startX1 - endX1;
double C1 = A1 * startX1 + B1 * startY1;
double A2 = endY2 - startY2;
double B2 = startX2 - endX2;
double C2 = A2 * startX2 + B2 * startY2;
double det = (A1 * B2) - (A2 * B1);
if (Math.abs(det) > SpatialUtils.doubleEpsilon()) {
// det != 0
double x = (B2 * C1 - B1 * C2) / det;
double y = (A1 * C2 - A2 * C1) / det;
if ((x >= Math.min(startX1, endX1) && x <= Math.max(startX1, endX1)) && (y >= Math.min(startY1, endY1) && y <= Math.max(startY1, endY1))) {
if ((x >= Math.min(startX2, endX2) && x <= Math.max(startX2, endX2)) && (y >= Math.min(startY2, endY2) && y <= Math.max(startY2, endY2))) {
return true;
}
}
}
return false;
}
private boolean linePolygonIntersection(byte[] bytes0, int offset0, byte[] bytes1, int offset1) throws HyracksDataException {
double startX1 = ADoubleSerializerDeserializer.getDouble(bytes0, offset0 + ALineSerializerDeserializer.getStartPointCoordinateOffset(Coordinate.X));
double startY1 = ADoubleSerializerDeserializer.getDouble(bytes0, offset0 + ALineSerializerDeserializer.getStartPointCoordinateOffset(Coordinate.Y));
double endX1 = ADoubleSerializerDeserializer.getDouble(bytes0, offset0 + ALineSerializerDeserializer.getEndPointCoordinateOffset(Coordinate.X));
double endY1 = ADoubleSerializerDeserializer.getDouble(bytes0, offset0 + ALineSerializerDeserializer.getEndPointCoordinateOffset(Coordinate.Y));
int numOfPoints1 = AInt16SerializerDeserializer.getShort(bytes1, offset1 + APolygonSerializerDeserializer.getNumberOfPointsOffset());
if (numOfPoints1 < 3) {
throw new InvalidDataFormatException(getIdentifier(), ATypeTag.SERIALIZED_POLYGON_TYPE_TAG);
}
for (int i = 0; i < numOfPoints1; i++) {
double startX2 = ADoubleSerializerDeserializer.getDouble(bytes1, offset1 + APolygonSerializerDeserializer.getCoordinateOffset(i, Coordinate.X));
double startY2 = ADoubleSerializerDeserializer.getDouble(bytes1, offset1 + APolygonSerializerDeserializer.getCoordinateOffset(i, Coordinate.Y));
double endX2;
double endY2;
if (i + 1 == numOfPoints1) {
endX2 = ADoubleSerializerDeserializer.getDouble(bytes1, offset1 + APolygonSerializerDeserializer.getCoordinateOffset(0, Coordinate.X));
endY2 = ADoubleSerializerDeserializer.getDouble(bytes1, offset1 + APolygonSerializerDeserializer.getCoordinateOffset(0, Coordinate.Y));
} else {
endX2 = ADoubleSerializerDeserializer.getDouble(bytes1, offset1 + APolygonSerializerDeserializer.getCoordinateOffset(i + 1, Coordinate.X));
endY2 = ADoubleSerializerDeserializer.getDouble(bytes1, offset1 + APolygonSerializerDeserializer.getCoordinateOffset(i + 1, Coordinate.Y));
}
boolean intersect = lineLineIntersection(startX1, startY1, endX1, endY1, startX2, startY2, endX2, endY2);
if (intersect) {
return true;
}
}
return false;
}
private boolean lineRectangleIntersection(byte[] bytes0, int offset0, byte[] bytes1, int offset1) throws HyracksDataException {
double startX1 = ADoubleSerializerDeserializer.getDouble(bytes0, offset0 + ALineSerializerDeserializer.getStartPointCoordinateOffset(Coordinate.X));
double startY1 = ADoubleSerializerDeserializer.getDouble(bytes0, offset0 + ALineSerializerDeserializer.getStartPointCoordinateOffset(Coordinate.Y));
double endX1 = ADoubleSerializerDeserializer.getDouble(bytes0, offset0 + ALineSerializerDeserializer.getEndPointCoordinateOffset(Coordinate.X));
double endY1 = ADoubleSerializerDeserializer.getDouble(bytes0, offset0 + ALineSerializerDeserializer.getEndPointCoordinateOffset(Coordinate.Y));
double x1 = ADoubleSerializerDeserializer.getDouble(bytes1, offset1 + ARectangleSerializerDeserializer.getBottomLeftCoordinateOffset(Coordinate.X));
double y1 = ADoubleSerializerDeserializer.getDouble(bytes1, offset1 + ARectangleSerializerDeserializer.getBottomLeftCoordinateOffset(Coordinate.Y));
double x2 = ADoubleSerializerDeserializer.getDouble(bytes1, offset1 + ARectangleSerializerDeserializer.getUpperRightCoordinateOffset(Coordinate.X));
double y2 = ADoubleSerializerDeserializer.getDouble(bytes1, offset1 + ARectangleSerializerDeserializer.getUpperRightCoordinateOffset(Coordinate.Y));
if (lineLineIntersection(startX1, startY1, endX1, endY1, x1, y1, x1, y2) || lineLineIntersection(startX1, startY1, endX1, endY1, x1, y2, x2, y2) || lineLineIntersection(startX1, startY1, endX1, endY1, x2, y2, x2, y1) || lineLineIntersection(startX1, startY1, endX1, endY1, x2, y1, x1, y1)) {
return true;
}
return false;
}
private boolean lineCircleIntersection(byte[] bytes0, int offset0, byte[] bytes1, int offset1) throws HyracksDataException {
double startX = ADoubleSerializerDeserializer.getDouble(bytes0, offset0 + ALineSerializerDeserializer.getStartPointCoordinateOffset(Coordinate.X));
double startY = ADoubleSerializerDeserializer.getDouble(bytes0, offset0 + ALineSerializerDeserializer.getStartPointCoordinateOffset(Coordinate.Y));
double endX = ADoubleSerializerDeserializer.getDouble(bytes0, offset0 + ALineSerializerDeserializer.getEndPointCoordinateOffset(Coordinate.X));
double endY = ADoubleSerializerDeserializer.getDouble(bytes0, offset0 + ALineSerializerDeserializer.getEndPointCoordinateOffset(Coordinate.Y));
double cX = ADoubleSerializerDeserializer.getDouble(bytes1, offset1 + ACircleSerializerDeserializer.getCenterPointCoordinateOffset(Coordinate.X));
double cY = ADoubleSerializerDeserializer.getDouble(bytes1, offset1 + ACircleSerializerDeserializer.getCenterPointCoordinateOffset(Coordinate.Y));
double radius = ADoubleSerializerDeserializer.getDouble(bytes1, offset1 + ACircleSerializerDeserializer.getRadiusOffset());
double dx = endX - startX;
double dy = endY - startY;
double t = -((startX - cX) * dx + (startY - cY) * dy) / ((dx * dx) + (dy * dy));
if (t < 0.0) {
t = 0.0;
} else if (t > 1.0) {
t = 1.0;
}
dx = (startX + t * (endX - startX)) - cX;
dy = (startY + t * (endY - startY)) - cY;
double rt = (dx * dx) + (dy * dy);
if (rt <= (radius * radius)) {
return true;
}
return false;
}
private boolean findEar(byte[] bytes, int offset, int u, int v, int w, int n, IntArray pointsOffsets) throws HyracksDataException {
int p;
double Ax, Ay, Bx, By, Cx, Cy, Px, Py;
Ax = ADoubleSerializerDeserializer.getDouble(bytes, offset + APolygonSerializerDeserializer.getCoordinateOffset(pointsOffsets.get(u), Coordinate.X));
Ay = ADoubleSerializerDeserializer.getDouble(bytes, offset + APolygonSerializerDeserializer.getCoordinateOffset(pointsOffsets.get(u), Coordinate.Y));
Bx = ADoubleSerializerDeserializer.getDouble(bytes, offset + APolygonSerializerDeserializer.getCoordinateOffset(pointsOffsets.get(v), Coordinate.X));
By = ADoubleSerializerDeserializer.getDouble(bytes, offset + APolygonSerializerDeserializer.getCoordinateOffset(pointsOffsets.get(v), Coordinate.Y));
Cx = ADoubleSerializerDeserializer.getDouble(bytes, offset + APolygonSerializerDeserializer.getCoordinateOffset(pointsOffsets.get(w), Coordinate.X));
Cy = ADoubleSerializerDeserializer.getDouble(bytes, offset + APolygonSerializerDeserializer.getCoordinateOffset(pointsOffsets.get(w), Coordinate.Y));
if (SpatialUtils.doubleEpsilon() > (((Bx - Ax) * (Cy - Ay)) - ((By - Ay) * (Cx - Ax)))) {
return false;
}
for (p = 0; p < n; p++) {
if ((p == u) || (p == v) || (p == w)) {
continue;
}
Px = ADoubleSerializerDeserializer.getDouble(bytes, offset + APolygonSerializerDeserializer.getCoordinateOffset(pointsOffsets.get(p), Coordinate.X));
Py = ADoubleSerializerDeserializer.getDouble(bytes, offset + APolygonSerializerDeserializer.getCoordinateOffset(pointsOffsets.get(p), Coordinate.Y));
if (pointInsideTriangle(Ax, Ay, Bx, By, Cx, Cy, Px, Py)) {
return false;
}
}
return true;
}
private int triangulatePolygon(byte[] bytes, int offset, int numOfPoints, IntArray pointsOffsets, DoubleArray trianglesX, DoubleArray trianglesY, int triangleId, int nonSimplePolygonDetection, int middleVertex) throws HyracksDataException {
if (numOfPoints < 3) {
return -1;
}
boolean foundEar = false;
int v = middleVertex;
while (!foundEar) {
if (0 >= (nonSimplePolygonDetection--)) {
throw new InvalidDataFormatException(getIdentifier(), ATypeTag.SERIALIZED_POLYGON_TYPE_TAG);
}
int u = v;
if (numOfPoints <= u) {
u = 0;
}
v = u + 1;
if (numOfPoints <= v) {
v = 0;
}
int w = v + 1;
if (numOfPoints <= w) {
w = 0;
}
if (findEar(bytes, offset, u, v, w, numOfPoints, pointsOffsets)) {
int s, t;
addRectangle(trianglesX, trianglesY);
SpatialUtils.setTriangleXCoordinate(trianglesX, triangleId, 0, ADoubleSerializerDeserializer.getDouble(bytes, offset + APolygonSerializerDeserializer.getCoordinateOffset(pointsOffsets.get(u), Coordinate.X)));
SpatialUtils.setTriangleYCoordinate(trianglesY, triangleId, 0, ADoubleSerializerDeserializer.getDouble(bytes, offset + APolygonSerializerDeserializer.getCoordinateOffset(pointsOffsets.get(u), Coordinate.Y)));
SpatialUtils.setTriangleXCoordinate(trianglesX, triangleId, 1, ADoubleSerializerDeserializer.getDouble(bytes, offset + APolygonSerializerDeserializer.getCoordinateOffset(pointsOffsets.get(v), Coordinate.X)));
SpatialUtils.setTriangleYCoordinate(trianglesY, triangleId, 1, ADoubleSerializerDeserializer.getDouble(bytes, offset + APolygonSerializerDeserializer.getCoordinateOffset(pointsOffsets.get(v), Coordinate.Y)));
SpatialUtils.setTriangleXCoordinate(trianglesX, triangleId, 2, ADoubleSerializerDeserializer.getDouble(bytes, offset + APolygonSerializerDeserializer.getCoordinateOffset(pointsOffsets.get(w), Coordinate.X)));
SpatialUtils.setTriangleYCoordinate(trianglesY, triangleId, 2, ADoubleSerializerDeserializer.getDouble(bytes, offset + APolygonSerializerDeserializer.getCoordinateOffset(pointsOffsets.get(w), Coordinate.Y)));
// remove v from polygon
for (s = v, t = v + 1; t < numOfPoints; s++, t++) {
pointsOffsets.get()[s] = pointsOffsets.get(t);
}
foundEar = true;
}
}
return v;
}
private boolean triangleTriangleIntersection(DoubleArray trianglesX0, DoubleArray trianglesY0, int triangleId0, DoubleArray trianglesX1, DoubleArray trianglesY1, int triangleId1) throws HyracksDataException {
for (int side = 0; side < 3; side++) {
spatialUtils.findNormals(trianglesX0, trianglesY0, triangleId0, side);
spatialUtils.projectPolygon(trianglesX0, trianglesY0, triangleId0, spatialUtils.getXAxis(), spatialUtils.getYAxis());
double min1 = spatialUtils.getMinProjection();
double max1 = spatialUtils.getMaxProjection();
spatialUtils.projectPolygon(trianglesX1, trianglesY1, triangleId1, spatialUtils.getXAxis(), spatialUtils.getYAxis());
double min2 = spatialUtils.getMinProjection();
double max2 = spatialUtils.getMaxProjection();
if (max1 < min2 || min1 > max2) {
return false;
}
}
return true;
}
private boolean pointInsideTriangle(double x1, double y1, double x2, double y2, double x3, double y3, double pX, double pY) {
return pointsOnSameSide(pX, pY, x1, y1, x2, y2, x3, y3) && pointsOnSameSide(pX, pY, x2, y2, x1, y1, x3, y3) && pointsOnSameSide(pX, pY, x3, y3, x1, y1, x2, y2);
}
private boolean pointsOnSameSide(double pX, double pY, double x1, double y1, double x2, double y2, double x3, double y3) {
double cp1 = SpatialUtils.crossProduct(x3 - x2, y3 - y2, pX - x2, pY - y2);
double cp2 = SpatialUtils.crossProduct(x3 - x2, y3 - y2, x1 - x2, y1 - y2);
return (cp1 * cp2) >= 0.0;
}
private boolean circleTriangleIntersection(byte[] bytes0, int offset0, DoubleArray trianglesX, DoubleArray trianglesY, int triangleId) throws HyracksDataException {
// separating axis theorem
double cX = ADoubleSerializerDeserializer.getDouble(bytes0, offset0 + ACircleSerializerDeserializer.getCenterPointCoordinateOffset(Coordinate.X));
double cY = ADoubleSerializerDeserializer.getDouble(bytes0, offset0 + ACircleSerializerDeserializer.getCenterPointCoordinateOffset(Coordinate.Y));
double radius = ADoubleSerializerDeserializer.getDouble(bytes0, offset0 + ACircleSerializerDeserializer.getRadiusOffset());
double distance = Double.MAX_VALUE;
double distanceSquared;
double temp;
double closestPointX = 0.0;
double closestPointY = 0.0;
for (int i = 0; i < 3; i++) {
double pX = SpatialUtils.getTriangleXCoordinate(trianglesX, triangleId, i);
double pY = SpatialUtils.getTriangleXCoordinate(trianglesY, triangleId, i);
distanceSquared = (cX - pX) * (cX - pX) + (cY - pY) * (cY - pY);
if (distanceSquared < distance) {
distance = distanceSquared;
closestPointX = pX;
closestPointY = pY;
}
}
double x = Math.abs(cX - closestPointX);
double y = Math.abs(cY - closestPointY);
temp = Math.sqrt(SpatialUtils.dotProduct(x, y, x, y));
x /= temp;
y /= temp;
spatialUtils.projectPolygon(trianglesX, trianglesY, triangleId, x, y);
double min1 = spatialUtils.getMinProjection();
double max1 = spatialUtils.getMaxProjection();
double dotProduct = SpatialUtils.dotProduct(x, y, cX, cY);
double max2 = dotProduct + radius;
double min2 = dotProduct - radius;
if (max1 < min2 || min1 > max2) {
return false;
}
for (int side = 0; side < 3; side++) {
spatialUtils.findNormals(trianglesX, trianglesY, triangleId, side);
spatialUtils.projectPolygon(trianglesX, trianglesY, triangleId, spatialUtils.getXAxis(), spatialUtils.getYAxis());
min1 = spatialUtils.getMinProjection();
max1 = spatialUtils.getMaxProjection();
dotProduct = SpatialUtils.dotProduct(spatialUtils.getXAxis(), spatialUtils.getYAxis(), cX, cY);
max2 = dotProduct + radius;
min2 = dotProduct - radius;
if (max1 < min2 || min1 > max2) {
return false;
}
}
return true;
}
private boolean circleCircleIntersection(byte[] bytes0, int offset0, byte[] bytes1, int offset1) throws HyracksDataException {
double cX0 = ADoubleSerializerDeserializer.getDouble(bytes0, offset0 + ACircleSerializerDeserializer.getCenterPointCoordinateOffset(Coordinate.X));
double cY0 = ADoubleSerializerDeserializer.getDouble(bytes0, offset0 + ACircleSerializerDeserializer.getCenterPointCoordinateOffset(Coordinate.Y));
double radius0 = ADoubleSerializerDeserializer.getDouble(bytes0, offset0 + ACircleSerializerDeserializer.getRadiusOffset());
double cX1 = ADoubleSerializerDeserializer.getDouble(bytes1, offset1 + ACircleSerializerDeserializer.getCenterPointCoordinateOffset(Coordinate.X));
double cY1 = ADoubleSerializerDeserializer.getDouble(bytes1, offset1 + ACircleSerializerDeserializer.getCenterPointCoordinateOffset(Coordinate.Y));
double radius1 = ADoubleSerializerDeserializer.getDouble(bytes1, offset1 + ACircleSerializerDeserializer.getRadiusOffset());
double distanceSquared = SpatialUtils.dotProduct(cX0 - cX1, cY0 - cY1, cX0 - cX1, cY0 - cY1);
double radiusDistanceSquared = (radius0 + radius1) * (radius0 + radius1);
if (distanceSquared <= radiusDistanceSquared) {
return true;
}
return false;
}
private void getCounterClockWisePolygon(byte[] bytes, int offset, IntArray pointsOffsets, int numOfPoints) throws HyracksDataException {
pointsOffsets.reset();
if (SpatialUtils.polygonArea(bytes, offset, numOfPoints) > 0.0) {
for (int i = 0; i < numOfPoints; i++) {
pointsOffsets.add(i);
}
} else {
for (int i = 0; i < numOfPoints; i++) {
pointsOffsets.add((numOfPoints - 1) - i);
}
}
}
private boolean pointInRectangle(byte[] bytes0, int offset0, byte[] bytes1, int offset1) throws HyracksDataException {
double pX = ADoubleSerializerDeserializer.getDouble(bytes0, offset0 + APointSerializerDeserializer.getCoordinateOffset(Coordinate.X));
double pY = ADoubleSerializerDeserializer.getDouble(bytes0, offset0 + APointSerializerDeserializer.getCoordinateOffset(Coordinate.Y));
double x1 = ADoubleSerializerDeserializer.getDouble(bytes1, offset1 + ARectangleSerializerDeserializer.getBottomLeftCoordinateOffset(Coordinate.X));
double y1 = ADoubleSerializerDeserializer.getDouble(bytes1, offset1 + ARectangleSerializerDeserializer.getBottomLeftCoordinateOffset(Coordinate.Y));
double x2 = ADoubleSerializerDeserializer.getDouble(bytes1, offset1 + ARectangleSerializerDeserializer.getUpperRightCoordinateOffset(Coordinate.X));
double y2 = ADoubleSerializerDeserializer.getDouble(bytes1, offset1 + ARectangleSerializerDeserializer.getUpperRightCoordinateOffset(Coordinate.Y));
if (pointInsideTriangle(x1, y1, x1, y2, x2, y2, pX, pY) || pointInsideTriangle(x1, y1, x2, y1, x2, y2, pX, pY)) {
return true;
}
return false;
}
private void addRectangle(DoubleArray trianglesX, DoubleArray trianglesY) {
for (int i = 0; i < 3; i++) {
double temp = 0;
trianglesX.add(temp);
trianglesY.add(temp);
}
}
private boolean rectangleCircleIntersection(byte[] bytes0, int offset0, byte[] bytes1, int offset1) throws HyracksDataException {
triangulateRectangle(bytes0, offset0, trianglesX0, trianglesY0);
boolean res = false;
// 2 triangles in a rectangle
for (int i = 0; i < 2; i++) {
res = circleTriangleIntersection(bytes1, offset1, trianglesX0, trianglesY0, i);
if (res) {
break;
}
}
return res;
}
private void triangulateRectangle(byte[] bytes, int offset, DoubleArray trianglesX, DoubleArray trianglesY) throws HyracksDataException {
double x1 = ADoubleSerializerDeserializer.getDouble(bytes, offset + ARectangleSerializerDeserializer.getBottomLeftCoordinateOffset(Coordinate.X));
double y1 = ADoubleSerializerDeserializer.getDouble(bytes, offset + ARectangleSerializerDeserializer.getBottomLeftCoordinateOffset(Coordinate.Y));
double x2 = ADoubleSerializerDeserializer.getDouble(bytes, offset + ARectangleSerializerDeserializer.getUpperRightCoordinateOffset(Coordinate.X));
double y2 = ADoubleSerializerDeserializer.getDouble(bytes, offset + ARectangleSerializerDeserializer.getUpperRightCoordinateOffset(Coordinate.Y));
trianglesX.reset();
trianglesY.reset();
addRectangle(trianglesX, trianglesY);
addRectangle(trianglesX, trianglesY);
SpatialUtils.setTriangleXCoordinate(trianglesX, 0, 0, x1);
SpatialUtils.setTriangleYCoordinate(trianglesY, 0, 0, y1);
SpatialUtils.setTriangleXCoordinate(trianglesX, 0, 1, x2);
SpatialUtils.setTriangleYCoordinate(trianglesY, 0, 1, y1);
SpatialUtils.setTriangleXCoordinate(trianglesX, 0, 2, x2);
SpatialUtils.setTriangleYCoordinate(trianglesY, 0, 2, y2);
SpatialUtils.setTriangleXCoordinate(trianglesX, 1, 0, x2);
SpatialUtils.setTriangleYCoordinate(trianglesY, 1, 0, y2);
SpatialUtils.setTriangleXCoordinate(trianglesX, 1, 1, x1);
SpatialUtils.setTriangleYCoordinate(trianglesY, 1, 1, y2);
SpatialUtils.setTriangleXCoordinate(trianglesX, 1, 2, x1);
SpatialUtils.setTriangleYCoordinate(trianglesY, 1, 2, y1);
}
private boolean rectanglePolygonIntersection(byte[] bytes0, int offset0, byte[] bytes1, int offset1) throws HyracksDataException {
int numOfPoints1 = AInt16SerializerDeserializer.getShort(bytes1, offset1 + APolygonSerializerDeserializer.getNumberOfPointsOffset());
if (numOfPoints1 < 3) {
throw new InvalidDataFormatException(getIdentifier(), ATypeTag.SERIALIZED_POLYGON_TYPE_TAG);
}
getCounterClockWisePolygon(bytes1, offset1, pointsOffsets1, numOfPoints1);
int nonSimplePolygonDetection1 = 2 * numOfPoints1;
int middleVertex1 = numOfPoints1 - 1;
int numOfTriangles1 = 0;
trianglesX1.reset();
trianglesY1.reset();
while (true) {
middleVertex1 = triangulatePolygon(bytes1, offset1, numOfPoints1, pointsOffsets1, trianglesX1, trianglesY1, numOfTriangles1, nonSimplePolygonDetection1, middleVertex1);
if (middleVertex1 == -1) {
break;
}
numOfPoints1--;
nonSimplePolygonDetection1 = 2 * numOfPoints1;
numOfTriangles1++;
}
triangulateRectangle(bytes0, offset0, trianglesX0, trianglesY0);
boolean res = false;
// 2 triangles in a rectangle
for (int j = 0; j < 2; j++) {
for (int i = 0; i < numOfTriangles1; i++) {
res = triangleTriangleIntersection(trianglesX1, trianglesY1, i, trianglesX0, trianglesY0, j);
if (res) {
res = triangleTriangleIntersection(trianglesX0, trianglesY0, j, trianglesX1, trianglesY1, i);
if (res) {
return true;
}
}
}
}
return false;
}
private boolean polygonCircleIntersection(byte[] bytes0, int offset0, byte[] bytes1, int offset1) throws HyracksDataException {
int numOfPoints = AInt16SerializerDeserializer.getShort(bytes0, offset0 + APolygonSerializerDeserializer.getNumberOfPointsOffset());
if (numOfPoints < 3) {
throw new InvalidDataFormatException(getIdentifier(), ATypeTag.SERIALIZED_POLYGON_TYPE_TAG);
}
getCounterClockWisePolygon(bytes0, offset0, pointsOffsets0, numOfPoints);
int nonSimplePolygonDetection = 2 * numOfPoints;
int middleVertex = numOfPoints - 1;
int numOfTriangles = 0;
trianglesX0.reset();
trianglesY0.reset();
boolean res = false;
while (true) {
middleVertex = triangulatePolygon(bytes0, offset0, numOfPoints, pointsOffsets0, trianglesX0, trianglesY0, numOfTriangles, nonSimplePolygonDetection, middleVertex);
if (middleVertex == -1) {
break;
}
numOfPoints--;
nonSimplePolygonDetection = 2 * numOfPoints;
numOfTriangles++;
int lastTriangle = (trianglesX0.length() / 3) - 1;
res = circleTriangleIntersection(bytes1, offset1, trianglesX0, trianglesY0, lastTriangle);
if (res) {
return true;
}
}
return false;
}
@Override
public void evaluate(IFrameTupleReference tuple, IPointable result) throws HyracksDataException {
resultStorage.reset();
eval0.evaluate(tuple, inputArg0);
eval1.evaluate(tuple, inputArg1);
byte[] bytes0 = inputArg0.getByteArray();
byte[] bytes1 = inputArg1.getByteArray();
int offset0 = inputArg0.getStartOffset();
int offset1 = inputArg1.getStartOffset();
boolean res = false;
ATypeTag tag0 = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(bytes0[offset0]);
ATypeTag tag1 = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(bytes1[offset1]);
switch(tag0) {
case POINT:
switch(tag1) {
case POINT:
if (ascDoubleComp.compare(bytes0, offset0 + APointSerializerDeserializer.getCoordinateOffset(Coordinate.X), 8, bytes1, offset1 + APointSerializerDeserializer.getCoordinateOffset(Coordinate.X), 8) == 0) {
if (ascDoubleComp.compare(bytes0, offset0 + APointSerializerDeserializer.getCoordinateOffset(Coordinate.Y), 8, bytes1, offset1 + APointSerializerDeserializer.getCoordinateOffset(Coordinate.Y), 8) == 0) {
res = true;
}
}
break;
case LINE:
double pX = ADoubleSerializerDeserializer.getDouble(bytes0, offset0 + APointSerializerDeserializer.getCoordinateOffset(Coordinate.X));
double pY = ADoubleSerializerDeserializer.getDouble(bytes0, offset0 + APointSerializerDeserializer.getCoordinateOffset(Coordinate.Y));
double startX = ADoubleSerializerDeserializer.getDouble(bytes1, offset1 + ALineSerializerDeserializer.getStartPointCoordinateOffset(Coordinate.X));
double startY = ADoubleSerializerDeserializer.getDouble(bytes1, offset1 + ALineSerializerDeserializer.getStartPointCoordinateOffset(Coordinate.Y));
double endX = ADoubleSerializerDeserializer.getDouble(bytes1, offset1 + ALineSerializerDeserializer.getEndPointCoordinateOffset(Coordinate.X));
double endY = ADoubleSerializerDeserializer.getDouble(bytes1, offset1 + ALineSerializerDeserializer.getEndPointCoordinateOffset(Coordinate.Y));
res = pointOnLine(pX, pY, startX, startY, endX, endY);
break;
case POLYGON:
res = pointInPolygon(bytes0, offset0, bytes1, offset1);
break;
case CIRCLE:
res = pointInCircle(bytes0, offset0, bytes1, offset1);
break;
case RECTANGLE:
res = pointInRectangle(bytes0, offset0, bytes1, offset1);
break;
default:
throw new TypeMismatchException(getIdentifier(), 1, bytes1[offset1], ATypeTag.SERIALIZED_POINT_TYPE_TAG, ATypeTag.SERIALIZED_LINE_TYPE_TAG, ATypeTag.SERIALIZED_POLYGON_TYPE_TAG, ATypeTag.SERIALIZED_CIRCLE_TYPE_TAG, ATypeTag.SERIALIZED_RECTANGLE_TYPE_TAG);
}
break;
case LINE:
switch(tag1) {
case POINT:
double pX = ADoubleSerializerDeserializer.getDouble(bytes1, offset1 + APointSerializerDeserializer.getCoordinateOffset(Coordinate.X));
double pY = ADoubleSerializerDeserializer.getDouble(bytes1, offset1 + APointSerializerDeserializer.getCoordinateOffset(Coordinate.Y));
double startX = ADoubleSerializerDeserializer.getDouble(bytes0, offset0 + ALineSerializerDeserializer.getStartPointCoordinateOffset(Coordinate.X));
double startY = ADoubleSerializerDeserializer.getDouble(bytes0, offset0 + ALineSerializerDeserializer.getStartPointCoordinateOffset(Coordinate.Y));
double endX = ADoubleSerializerDeserializer.getDouble(bytes0, offset0 + ALineSerializerDeserializer.getEndPointCoordinateOffset(Coordinate.X));
double endY = ADoubleSerializerDeserializer.getDouble(bytes0, offset0 + ALineSerializerDeserializer.getEndPointCoordinateOffset(Coordinate.Y));
res = pointOnLine(pX, pY, startX, startY, endX, endY);
break;
case LINE:
double startX1 = ADoubleSerializerDeserializer.getDouble(bytes0, offset0 + ALineSerializerDeserializer.getStartPointCoordinateOffset(Coordinate.X));
double startY1 = ADoubleSerializerDeserializer.getDouble(bytes0, offset0 + ALineSerializerDeserializer.getStartPointCoordinateOffset(Coordinate.Y));
double endX1 = ADoubleSerializerDeserializer.getDouble(bytes0, offset0 + ALineSerializerDeserializer.getEndPointCoordinateOffset(Coordinate.X));
double endY1 = ADoubleSerializerDeserializer.getDouble(bytes0, offset0 + ALineSerializerDeserializer.getEndPointCoordinateOffset(Coordinate.Y));
double startX2 = ADoubleSerializerDeserializer.getDouble(bytes1, offset1 + ALineSerializerDeserializer.getStartPointCoordinateOffset(Coordinate.X));
double startY2 = ADoubleSerializerDeserializer.getDouble(bytes1, offset1 + ALineSerializerDeserializer.getStartPointCoordinateOffset(Coordinate.Y));
double endX2 = ADoubleSerializerDeserializer.getDouble(bytes1, offset1 + ALineSerializerDeserializer.getEndPointCoordinateOffset(Coordinate.X));
double endY2 = ADoubleSerializerDeserializer.getDouble(bytes1, offset1 + ALineSerializerDeserializer.getEndPointCoordinateOffset(Coordinate.Y));
res = lineLineIntersection(startX1, startY1, endX1, endY1, startX2, startY2, endX2, endY2);
break;
case POLYGON:
res = linePolygonIntersection(bytes0, offset0, bytes1, offset1);
break;
case CIRCLE:
res = lineCircleIntersection(bytes0, offset0, bytes1, offset1);
break;
case RECTANGLE:
res = lineRectangleIntersection(bytes0, offset0, bytes1, offset1);
break;
default:
throw new TypeMismatchException(getIdentifier(), 1, bytes1[offset1], ATypeTag.SERIALIZED_POINT_TYPE_TAG, ATypeTag.SERIALIZED_LINE_TYPE_TAG, ATypeTag.SERIALIZED_POLYGON_TYPE_TAG, ATypeTag.SERIALIZED_CIRCLE_TYPE_TAG, ATypeTag.SERIALIZED_RECTANGLE_TYPE_TAG);
}
break;
case POLYGON:
switch(tag1) {
case POINT:
res = pointInPolygon(bytes1, offset1, bytes0, offset0);
break;
case LINE:
res = linePolygonIntersection(bytes1, offset1, bytes0, offset0);
break;
case POLYGON:
int numOfPoints0 = AInt16SerializerDeserializer.getShort(bytes0, offset0 + APolygonSerializerDeserializer.getNumberOfPointsOffset());
int numOfPoints1 = AInt16SerializerDeserializer.getShort(bytes1, offset1 + APolygonSerializerDeserializer.getNumberOfPointsOffset());
if (numOfPoints0 < 3 || numOfPoints1 < 3) {
throw new InvalidDataFormatException(getIdentifier(), ATypeTag.SERIALIZED_POLYGON_TYPE_TAG);
}
getCounterClockWisePolygon(bytes0, offset0, pointsOffsets0, numOfPoints0);
getCounterClockWisePolygon(bytes1, offset1, pointsOffsets1, numOfPoints1);
int nonSimplePolygonDetection0 = 2 * numOfPoints0;
int nonSimplePolygonDetection1 = 2 * numOfPoints1;
boolean intersect = false;
int middleVertex0 = numOfPoints0 - 1;
int numOfTriangles1 = 0;
int middleVertex1 = numOfPoints1 - 1;
trianglesX1.reset();
trianglesY1.reset();
while (true) {
middleVertex1 = triangulatePolygon(bytes1, offset1, numOfPoints1, pointsOffsets1, trianglesX1, trianglesY1, numOfTriangles1, nonSimplePolygonDetection1, middleVertex1);
if (middleVertex1 == -1) {
break;
}
numOfPoints1--;
nonSimplePolygonDetection1 = 2 * numOfPoints1;
numOfTriangles1++;
}
int numOfTriangles0 = 0;
trianglesX0.reset();
trianglesY0.reset();
while (true) {
middleVertex0 = triangulatePolygon(bytes0, offset0, numOfPoints0, pointsOffsets0, trianglesX0, trianglesY0, numOfTriangles0, nonSimplePolygonDetection0, middleVertex0);
if (middleVertex0 == -1) {
break;
}
numOfPoints0--;
nonSimplePolygonDetection0 = 2 * numOfPoints0;
numOfTriangles0++;
int lastTriangle = (trianglesX0.length() / 3) - 1;
for (int i = 0; i < numOfTriangles1; i++) {
res = triangleTriangleIntersection(trianglesX0, trianglesY0, lastTriangle, trianglesX1, trianglesY1, i);
if (res) {
res = triangleTriangleIntersection(trianglesX1, trianglesY1, i, trianglesX0, trianglesY0, lastTriangle);
if (res) {
intersect = true;
break;
}
}
}
if (intersect) {
break;
}
}
break;
case CIRCLE:
res = polygonCircleIntersection(bytes0, offset0, bytes1, offset1);
break;
case RECTANGLE:
res = rectanglePolygonIntersection(bytes1, offset1, bytes0, offset0);
break;
default:
throw new TypeMismatchException(getIdentifier(), 1, bytes1[offset1], ATypeTag.SERIALIZED_POINT_TYPE_TAG, ATypeTag.SERIALIZED_LINE_TYPE_TAG, ATypeTag.SERIALIZED_POLYGON_TYPE_TAG, ATypeTag.SERIALIZED_CIRCLE_TYPE_TAG, ATypeTag.SERIALIZED_RECTANGLE_TYPE_TAG);
}
break;
case CIRCLE:
switch(tag1) {
case POINT:
res = pointInCircle(bytes1, offset1, bytes0, offset0);
break;
case LINE:
res = lineCircleIntersection(bytes1, offset1, bytes0, offset0);
break;
case POLYGON:
res = polygonCircleIntersection(bytes1, offset1, bytes0, offset0);
break;
case CIRCLE:
res = circleCircleIntersection(bytes0, offset0, bytes1, offset1);
break;
case RECTANGLE:
res = rectangleCircleIntersection(bytes1, offset1, bytes0, offset0);
break;
default:
throw new TypeMismatchException(getIdentifier(), 1, bytes1[offset1], ATypeTag.SERIALIZED_POINT_TYPE_TAG, ATypeTag.SERIALIZED_LINE_TYPE_TAG, ATypeTag.SERIALIZED_POLYGON_TYPE_TAG, ATypeTag.SERIALIZED_CIRCLE_TYPE_TAG, ATypeTag.SERIALIZED_RECTANGLE_TYPE_TAG);
}
break;
case RECTANGLE:
switch(tag1) {
case POINT:
res = pointInRectangle(bytes1, offset1, bytes0, offset0);
break;
case LINE:
res = lineRectangleIntersection(bytes1, offset1, bytes0, offset0);
break;
case POLYGON:
res = rectanglePolygonIntersection(bytes0, offset0, bytes1, offset1);
break;
case CIRCLE:
res = rectangleCircleIntersection(bytes0, offset0, bytes1, offset1);
break;
case RECTANGLE:
triangulateRectangle(bytes0, offset0, trianglesX0, trianglesY0);
triangulateRectangle(bytes1, offset1, trianglesX1, trianglesY1);
boolean intersect = false;
// 2 triangles in a rectangle
for (int j = 0; j < 2; j++) {
for (int i = 0; i < 2; i++) {
res = triangleTriangleIntersection(trianglesX1, trianglesY1, i, trianglesX0, trianglesY0, j);
if (res) {
res = triangleTriangleIntersection(trianglesX0, trianglesY0, j, trianglesX1, trianglesY1, i);
if (res) {
intersect = true;
break;
}
}
}
if (intersect) {
break;
}
}
break;
default:
throw new TypeMismatchException(getIdentifier(), 1, bytes1[offset1], ATypeTag.SERIALIZED_POINT_TYPE_TAG, ATypeTag.SERIALIZED_LINE_TYPE_TAG, ATypeTag.SERIALIZED_POLYGON_TYPE_TAG, ATypeTag.SERIALIZED_CIRCLE_TYPE_TAG, ATypeTag.SERIALIZED_RECTANGLE_TYPE_TAG);
}
break;
default:
throw new TypeMismatchException(getIdentifier(), 0, bytes0[offset0], ATypeTag.SERIALIZED_POINT_TYPE_TAG, ATypeTag.SERIALIZED_LINE_TYPE_TAG, ATypeTag.SERIALIZED_POLYGON_TYPE_TAG, ATypeTag.SERIALIZED_CIRCLE_TYPE_TAG, ATypeTag.SERIALIZED_RECTANGLE_TYPE_TAG);
}
ABoolean aResult = res ? ABoolean.TRUE : ABoolean.FALSE;
aBooleanSerDer.serialize(aResult, out);
result.set(resultStorage);
}
};
}
};
}
use of org.apache.hyracks.api.dataflow.value.IBinaryComparator in project asterixdb by apache.
the class FieldPrefixCompressor method compress.
@Override
public boolean compress(ITreeIndexFrame indexFrame, MultiComparator cmp) throws Exception {
BTreeFieldPrefixNSMLeafFrame frame = (BTreeFieldPrefixNSMLeafFrame) indexFrame;
int tupleCount = frame.getTupleCount();
if (tupleCount <= 0) {
frame.setPrefixTupleCount(0);
frame.setFreeSpaceOff(frame.getOrigFreeSpaceOff());
frame.setTotalFreeSpace(frame.getOrigTotalFreeSpace());
return false;
}
if (cmp.getKeyFieldCount() == 1) {
return false;
}
int uncompressedTupleCount = frame.getUncompressedTupleCount();
float ratio = (float) uncompressedTupleCount / (float) tupleCount;
if (ratio < ratioThreshold)
return false;
IBinaryComparator[] cmps = cmp.getComparators();
int fieldCount = typeTraits.length;
ByteBuffer buf = frame.getBuffer();
byte[] pageArray = buf.array();
IPrefixSlotManager slotManager = (IPrefixSlotManager) frame.getSlotManager();
// perform analysis pass
ArrayList<KeyPartition> keyPartitions = getKeyPartitions(frame, cmp, occurrenceThreshold);
if (keyPartitions.size() == 0)
return false;
// for each keyPartition, determine the best prefix length for
// compression, and count how many prefix tuple we would need in total
int totalSlotsNeeded = 0;
int totalPrefixBytes = 0;
for (KeyPartition kp : keyPartitions) {
for (int j = 0; j < kp.pmi.length; j++) {
int benefitMinusCost = kp.pmi[j].spaceBenefit - kp.pmi[j].spaceCost;
if (benefitMinusCost > kp.maxBenefitMinusCost) {
kp.maxBenefitMinusCost = benefitMinusCost;
kp.maxPmiIndex = j;
}
}
// ignore keyPartitions with no benefit and don't count bytes and slots needed
if (kp.maxBenefitMinusCost <= 0)
continue;
totalPrefixBytes += kp.pmi[kp.maxPmiIndex].prefixBytes;
totalSlotsNeeded += kp.pmi[kp.maxPmiIndex].prefixSlotsNeeded;
}
// we use a greedy heuristic to solve this "knapsack"-like problem
// (every keyPartition has a space savings and a number of slots
// required, but the number of slots are constrained by MAX_PREFIX_SLOTS)
// we sort the keyPartitions by maxBenefitMinusCost / prefixSlotsNeeded
// and later choose the top MAX_PREFIX_SLOTS
int[] newPrefixSlots;
if (totalSlotsNeeded > FieldPrefixSlotManager.MAX_PREFIX_SLOTS) {
// order keyPartitions by the heuristic function
SortByHeuristic heuristicComparator = new SortByHeuristic();
Collections.sort(keyPartitions, heuristicComparator);
int slotsUsed = 0;
int numberKeyPartitions = -1;
for (int i = 0; i < keyPartitions.size(); i++) {
KeyPartition kp = keyPartitions.get(i);
slotsUsed += kp.pmi[kp.maxPmiIndex].prefixSlotsNeeded;
if (slotsUsed > FieldPrefixSlotManager.MAX_PREFIX_SLOTS) {
numberKeyPartitions = i + 1;
slotsUsed -= kp.pmi[kp.maxPmiIndex].prefixSlotsNeeded;
break;
}
}
newPrefixSlots = new int[slotsUsed];
// remove irrelevant keyPartitions and adjust total prefix bytes
while (keyPartitions.size() >= numberKeyPartitions) {
int lastIndex = keyPartitions.size() - 1;
KeyPartition kp = keyPartitions.get(lastIndex);
if (kp.maxBenefitMinusCost > 0)
totalPrefixBytes -= kp.pmi[kp.maxPmiIndex].prefixBytes;
keyPartitions.remove(lastIndex);
}
// re-order keyPartitions by prefix (corresponding to original order)
SortByOriginalRank originalRankComparator = new SortByOriginalRank();
Collections.sort(keyPartitions, originalRankComparator);
} else {
newPrefixSlots = new int[totalSlotsNeeded];
}
int[] newTupleSlots = new int[tupleCount];
// WARNING: our hope is that compression is infrequent
// here we allocate a big chunk of memory to temporary hold the new, re-compressed tuple
// in general it is very hard to avoid this step
int prefixFreeSpace = frame.getOrigFreeSpaceOff();
int tupleFreeSpace = prefixFreeSpace + totalPrefixBytes;
byte[] buffer = new byte[buf.capacity()];
ByteBuffer byteBuffer = ByteBuffer.wrap(buffer);
// perform compression, and reorg
// we assume that the keyPartitions are sorted by the prefixes
// (i.e., in the logical target order)
int kpIndex = 0;
int tupleIndex = 0;
int prefixTupleIndex = 0;
uncompressedTupleCount = 0;
TypeAwareTupleWriter tupleWriter = new TypeAwareTupleWriter(typeTraits);
FieldPrefixTupleReference tupleToWrite = new FieldPrefixTupleReference(tupleWriter.createTupleReference());
tupleToWrite.setFieldCount(fieldCount);
while (tupleIndex < tupleCount) {
if (kpIndex < keyPartitions.size()) {
// beginning of keyPartition found, compress entire keyPartition
if (tupleIndex == keyPartitions.get(kpIndex).firstTupleIndex) {
// number of fields we decided to use for compression of this keyPartition
int fieldCountToCompress = keyPartitions.get(kpIndex).maxPmiIndex + 1;
int segmentStart = keyPartitions.get(kpIndex).firstTupleIndex;
int tuplesInSegment = 1;
FieldPrefixTupleReference prevTuple = new FieldPrefixTupleReference(tupleWriter.createTupleReference());
prevTuple.setFieldCount(fieldCount);
FieldPrefixTupleReference tuple = new FieldPrefixTupleReference(tupleWriter.createTupleReference());
tuple.setFieldCount(fieldCount);
for (int i = tupleIndex + 1; i <= keyPartitions.get(kpIndex).lastTupleIndex; i++) {
prevTuple.resetByTupleIndex(frame, i - 1);
tuple.resetByTupleIndex(frame, i);
// check if tuples match in fieldCountToCompress of their first fields
int prefixFieldsMatch = 0;
for (int j = 0; j < fieldCountToCompress; j++) {
if (cmps[j].compare(pageArray, prevTuple.getFieldStart(j), prevTuple.getFieldLength(j), pageArray, tuple.getFieldStart(j), tuple.getFieldLength(j)) == 0)
prefixFieldsMatch++;
else
break;
}
// the two tuples must match in exactly the number of fields we decided
// to compress for this keyPartition
int processSegments = 0;
if (prefixFieldsMatch == fieldCountToCompress)
tuplesInSegment++;
else
processSegments++;
if (i == keyPartitions.get(kpIndex).lastTupleIndex)
processSegments++;
for (int r = 0; r < processSegments; r++) {
// compress current segment and then start new segment
if (tuplesInSegment < occurrenceThreshold || fieldCountToCompress <= 0) {
// write tuples uncompressed
for (int j = 0; j < tuplesInSegment; j++) {
int slotNum = segmentStart + j;
tupleToWrite.resetByTupleIndex(frame, slotNum);
newTupleSlots[tupleCount - 1 - slotNum] = slotManager.encodeSlotFields(FieldPrefixSlotManager.TUPLE_UNCOMPRESSED, tupleFreeSpace);
tupleFreeSpace += tupleWriter.writeTuple(tupleToWrite, byteBuffer, tupleFreeSpace);
}
uncompressedTupleCount += tuplesInSegment;
} else {
// segment has enough tuples: compress segment, extract prefix,
// write prefix tuple to buffer, and set prefix slot
newPrefixSlots[newPrefixSlots.length - 1 - prefixTupleIndex] = slotManager.encodeSlotFields(fieldCountToCompress, prefixFreeSpace);
prefixFreeSpace += tupleWriter.writeTupleFields(prevTuple, 0, fieldCountToCompress, byteBuffer.array(), prefixFreeSpace);
// truncate tuples, write them to buffer, and set tuple slots
for (int j = 0; j < tuplesInSegment; j++) {
int currTupleIndex = segmentStart + j;
tupleToWrite.resetByTupleIndex(frame, currTupleIndex);
newTupleSlots[tupleCount - 1 - currTupleIndex] = slotManager.encodeSlotFields(prefixTupleIndex, tupleFreeSpace);
tupleFreeSpace += tupleWriter.writeTupleFields(tupleToWrite, fieldCountToCompress, fieldCount - fieldCountToCompress, byteBuffer.array(), tupleFreeSpace);
}
prefixTupleIndex++;
}
// begin new segment
segmentStart = i;
tuplesInSegment = 1;
}
}
tupleIndex = keyPartitions.get(kpIndex).lastTupleIndex;
kpIndex++;
} else {
// just write the tuple uncompressed
tupleToWrite.resetByTupleIndex(frame, tupleIndex);
newTupleSlots[tupleCount - 1 - tupleIndex] = slotManager.encodeSlotFields(FieldPrefixSlotManager.TUPLE_UNCOMPRESSED, tupleFreeSpace);
tupleFreeSpace += tupleWriter.writeTuple(tupleToWrite, byteBuffer, tupleFreeSpace);
uncompressedTupleCount++;
}
} else {
// just write the tuple uncompressed
tupleToWrite.resetByTupleIndex(frame, tupleIndex);
newTupleSlots[tupleCount - 1 - tupleIndex] = slotManager.encodeSlotFields(FieldPrefixSlotManager.TUPLE_UNCOMPRESSED, tupleFreeSpace);
tupleFreeSpace += tupleWriter.writeTuple(tupleToWrite, byteBuffer, tupleFreeSpace);
uncompressedTupleCount++;
}
tupleIndex++;
}
// sanity check to see if we have written exactly as many prefix bytes as computed before
if (prefixFreeSpace != frame.getOrigFreeSpaceOff() + totalPrefixBytes) {
throw new Exception("ERROR: Number of prefix bytes written don't match computed number");
}
// in some rare instances our procedure could even increase the space requirement which is very dangerous
// this can happen to to the greedy solution of the knapsack-like problem
// therefore, we check if the new space exceeds the page size to avoid the only danger of
// an increasing space
int totalSpace = tupleFreeSpace + newTupleSlots.length * slotManager.getSlotSize() + newPrefixSlots.length * slotManager.getSlotSize();
if (totalSpace > buf.capacity())
// just leave the page as is
return false;
// copy new tuple and new slots into original page
int freeSpaceAfterInit = frame.getOrigFreeSpaceOff();
System.arraycopy(buffer, freeSpaceAfterInit, pageArray, freeSpaceAfterInit, tupleFreeSpace - freeSpaceAfterInit);
// copy prefix slots
int slotOffRunner = buf.capacity() - slotManager.getSlotSize();
for (int i = 0; i < newPrefixSlots.length; i++) {
buf.putInt(slotOffRunner, newPrefixSlots[newPrefixSlots.length - 1 - i]);
slotOffRunner -= slotManager.getSlotSize();
}
// copy tuple slots
for (int i = 0; i < newTupleSlots.length; i++) {
buf.putInt(slotOffRunner, newTupleSlots[newTupleSlots.length - 1 - i]);
slotOffRunner -= slotManager.getSlotSize();
}
// update space fields, TODO: we need to update more fields
frame.setFreeSpaceOff(tupleFreeSpace);
frame.setPrefixTupleCount(newPrefixSlots.length);
frame.setUncompressedTupleCount(uncompressedTupleCount);
int totalFreeSpace = buf.capacity() - tupleFreeSpace - ((newTupleSlots.length + newPrefixSlots.length) * slotManager.getSlotSize());
frame.setTotalFreeSpace(totalFreeSpace);
return true;
}
use of org.apache.hyracks.api.dataflow.value.IBinaryComparator in project asterixdb by apache.
the class MicroPreClusteredGroupRuntimeFactory method createOneOutputPushRuntime.
@Override
public AbstractOneInputOneOutputPushRuntime createOneOutputPushRuntime(final IHyracksTaskContext ctx) throws HyracksDataException {
final IBinaryComparator[] comparators = new IBinaryComparator[comparatorFactories.length];
for (int i = 0; i < comparatorFactories.length; ++i) {
comparators[i] = comparatorFactories[i].createBinaryComparator();
}
return new AbstractOneInputOneOutputPushRuntime() {
private PreclusteredGroupWriter pgw;
@Override
public void open() throws HyracksDataException {
pgw = new PreclusteredGroupWriter(ctx, groupFields, comparators, aggregatorFactory, inRecordDesc, outRecordDesc, writer);
pgw.open();
}
@Override
public void nextFrame(ByteBuffer buffer) throws HyracksDataException {
pgw.nextFrame(buffer);
}
@Override
public void fail() throws HyracksDataException {
pgw.fail();
}
@Override
public void close() throws HyracksDataException {
pgw.close();
}
@Override
public void flush() throws HyracksDataException {
pgw.flush();
}
};
}
Aggregations