Skip to content

Commit

Permalink
ESQL: Add min and max to IntVector (elastic#108216)
Browse files Browse the repository at this point in the history
This adds `min` and `max` methods to `IntVector` which returns the
minimum and maximum values in the vector. It'll calculate that min and
max and cache it if required. This is useful because we use `IntVector`
as ordinals for things - and it's especially useful to know that the
`max` is less than the size of thing we're looking up.
  • Loading branch information
nik9000 authored May 6, 2024
1 parent e6b43a1 commit 0117ea1
Show file tree
Hide file tree
Showing 11 changed files with 275 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,22 @@ public IntVector filter(int... positions) {
return blockFactory().newConstantIntVector(value, positions.length);
}

/**
* The minimum value in the block.
*/
@Override
public int min() {
return value;
}

/**
* The maximum value in the block.
*/
@Override
public int max() {
return value;
}

@Override
public ElementType elementType() {
return ElementType.INT;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,16 @@ final class IntArrayVector extends AbstractVector implements IntVector {

private final int[] values;

/**
* The minimum value in the block.
*/
private Integer min;

/**
* The minimum value in the block.
*/
private Integer max;

IntArrayVector(int[] values, int positionCount, BlockFactory blockFactory) {
super(positionCount, blockFactory);
this.values = values;
Expand Down Expand Up @@ -92,6 +102,36 @@ public static long ramBytesEstimated(int[] values) {
return BASE_RAM_BYTES_USED + RamUsageEstimator.sizeOf(values);
}

/**
* The minimum value in the block.
*/
@Override
public int min() {
if (min == null) {
int v = Integer.MAX_VALUE;
for (int i = 0; i < getPositionCount(); i++) {
v = Math.min(v, values[i]);
}
min = v;
}
return min;
}

/**
* The maximum value in the block.
*/
@Override
public int max() {
if (max == null) {
int v = Integer.MIN_VALUE;
for (int i = 0; i < getPositionCount(); i++) {
v = Math.max(v, values[i]);
}
max = v;
}
return max;
}

@Override
public long ramBytesUsed() {
return ramBytesEstimated(values);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,16 @@ public final class IntBigArrayVector extends AbstractVector implements IntVector

private final IntArray values;

/**
* The minimum value in the block.
*/
private Integer min;

/**
* The minimum value in the block.
*/
private Integer max;

public IntBigArrayVector(IntArray values, int positionCount, BlockFactory blockFactory) {
super(positionCount, blockFactory);
this.values = values;
Expand Down Expand Up @@ -61,6 +71,36 @@ public int getInt(int position) {
return values.get(position);
}

/**
* The minimum value in the block.
*/
@Override
public int min() {
if (min == null) {
int v = values.get(0);
for (int i = 1; i < getPositionCount(); i++) {
v = Math.min(v, values.get(i));
}
min = v;
}
return min;
}

/**
* The maximum value in the block.
*/
@Override
public int max() {
if (max == null) {
int v = values.get(0);
for (int i = 1; i < getPositionCount(); i++) {
v = Math.max(v, values.get(i));
}
max = v;
}
return max;
}

@Override
public ElementType elementType() {
return ElementType.INT;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,16 @@ public sealed interface IntVector extends Vector permits ConstantIntVector, IntA
@Override
IntVector filter(int... positions);

/**
* The minimum value in the Vector. An empty Vector will return {@link Integer#MAX_VALUE}.
*/
int min();

/**
* The maximum value in the Vector. An empty Vector will return {@link Integer#MIN_VALUE}.
*/
int max();

/**
* Compares the given object with this vector for equality. Returns {@code true} if and only if the
* given object is a IntVector, and both vectors are {@link #equals(IntVector, IntVector) equal}.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,18 @@ public long getLong(int position) {
throw new UnsupportedOperationException("null vector");
}

@Override
public int min() {
assert false : "null vector";
throw new UnsupportedOperationException("null vector");
}

@Override
public int max() {
assert false : "null vector";
throw new UnsupportedOperationException("null vector");
}

@Override
public ElementType elementType() {
return ElementType.NULL;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,18 @@ $else$
private final $type$[] values;
$endif$

$if(int)$
/**
* The minimum value in the block.
*/
private Integer min;

/**
* The minimum value in the block.
*/
private Integer max;
$endif$

$Type$ArrayVector($if(BytesRef)$BytesRefArray$else$$type$[]$endif$ values, int positionCount, BlockFactory blockFactory) {
super(positionCount, blockFactory);
this.values = values;
Expand Down Expand Up @@ -158,6 +170,38 @@ $endif$
return BASE_RAM_BYTES_USED + RamUsageEstimator.sizeOf(values);
}

$if(int)$
/**
* The minimum value in the block.
*/
@Override
public int min() {
if (min == null) {
int v = Integer.MAX_VALUE;
for (int i = 0; i < getPositionCount(); i++) {
v = Math.min(v, values[i]);
}
min = v;
}
return min;
}

/**
* The maximum value in the block.
*/
@Override
public int max() {
if (max == null) {
int v = Integer.MIN_VALUE;
for (int i = 0; i < getPositionCount(); i++) {
v = Math.max(v, values[i]);
}
max = v;
}
return max;
}
$endif$

@Override
public long ramBytesUsed() {
return ramBytesEstimated(values);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,18 @@ public final class $Type$BigArrayVector extends AbstractVector implements $Type$

private final $Array$ values;

$if(int)$
/**
* The minimum value in the block.
*/
private Integer min;

/**
* The minimum value in the block.
*/
private Integer max;
$endif$

public $Type$BigArrayVector($Array$ values, int positionCount, BlockFactory blockFactory) {
super(positionCount, blockFactory);
this.values = values;
Expand Down Expand Up @@ -67,6 +79,38 @@ $endif$
return values.get(position);
}

$if(int)$
/**
* The minimum value in the block.
*/
@Override
public int min() {
if (min == null) {
int v = values.get(0);
for (int i = 1; i < getPositionCount(); i++) {
v = Math.min(v, values.get(i));
}
min = v;
}
return min;
}

/**
* The maximum value in the block.
*/
@Override
public int max() {
if (max == null) {
int v = values.get(0);
for (int i = 1; i < getPositionCount(); i++) {
v = Math.max(v, values.get(i));
}
max = v;
}
return max;
}
$endif$

@Override
public ElementType elementType() {
return ElementType.$TYPE$;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,24 @@ $endif$
return blockFactory().newConstant$Type$Vector(value, positions.length);
}

$if(int)$
/**
* The minimum value in the block.
*/
@Override
public int min() {
return value;
}

/**
* The maximum value in the block.
*/
@Override
public int max() {
return value;
}
$endif$

@Override
public ElementType elementType() {
return ElementType.$TYPE$;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,18 @@ $endif$
@Override
$Type$Vector filter(int... positions);

$if(int)$
/**
* The minimum value in the Vector. An empty Vector will return {@link Integer#MAX_VALUE}.
*/
int min();

/**
* The maximum value in the Vector. An empty Vector will return {@link Integer#MIN_VALUE}.
*/
int max();
$endif$

/**
* Compares the given object with this vector for equality. Returns {@code true} if and only if the
* given object is a $Type$Vector, and both vectors are {@link #equals($Type$Vector, $Type$Vector) equal}.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,8 @@ public void testIntBlock() {
}
assertLookup(block, positions(blockFactory, positionCount + 1000), singletonList(null));
assertEmptyLookup(blockFactory, block);
assertThat(block.asVector().min(), equalTo(0));
assertThat(block.asVector().max(), equalTo(positionCount - 1));

try (IntBlock.Builder blockBuilder = blockFactory.newIntBlockBuilder(1)) {
IntBlock copy = blockBuilder.copyFrom(block, 0, block.getPositionCount()).build();
Expand Down Expand Up @@ -228,6 +230,36 @@ public void testIntBlock() {
IntStream.range(0, positionCount).forEach(vectorBuilder::appendInt);
IntVector vector = vectorBuilder.build();
assertSingleValueDenseBlock(vector.asBlock());
assertThat(vector.min(), equalTo(0));
assertThat(vector.max(), equalTo(positionCount - 1));
releaseAndAssertBreaker(vector.asBlock());
}
}
}

public void testIntBlockEmpty() {
for (int i = 0; i < 1000; i++) {
assertThat(breaker.getUsed(), is(0L));
IntBlock block;
if (randomBoolean()) {
try (IntBlock.Builder blockBuilder = blockFactory.newIntBlockBuilder(0)) {
block = blockBuilder.build();
}
} else {
block = blockFactory.newIntArrayVector(new int[] {}, 0).asBlock();
}

assertThat(block.getPositionCount(), equalTo(0));
assertLookup(block, positions(blockFactory, 1000), singletonList(null));
assertEmptyLookup(blockFactory, block);
assertThat(block.asVector().min(), equalTo(Integer.MAX_VALUE));
assertThat(block.asVector().max(), equalTo(Integer.MIN_VALUE));
releaseAndAssertBreaker(block);

try (IntVector.Builder vectorBuilder = blockFactory.newIntVectorBuilder(0)) {
IntVector vector = vectorBuilder.build();
assertThat(vector.min(), equalTo(Integer.MAX_VALUE));
assertThat(vector.max(), equalTo(Integer.MIN_VALUE));
releaseAndAssertBreaker(vector.asBlock());
}
}
Expand All @@ -254,6 +286,8 @@ public void testConstantIntBlock() {
}
assertLookup(block, positions(blockFactory, positionCount + 1000), singletonList(null));
assertEmptyLookup(blockFactory, block);
assertThat(block.asVector().min(), equalTo(value));
assertThat(block.asVector().max(), equalTo(value));
releaseAndAssertBreaker(block);
}
}
Expand Down
Loading

0 comments on commit 0117ea1

Please sign in to comment.