Skip to content

Commit

Permalink
Further cleaned up PrimitiveArrays
Browse files Browse the repository at this point in the history
  • Loading branch information
fickludd committed Mar 30, 2017
1 parent 17bba54 commit 7723a60
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 56 deletions.
Expand Up @@ -28,7 +28,7 @@
import org.neo4j.collection.primitive.PrimitiveIntIterator;
import org.neo4j.collection.primitive.PrimitiveIntObjectMap;
import org.neo4j.collection.primitive.PrimitiveIntSet;
import org.neo4j.collection.primitive.PrimitiveSortedArraySet;
import org.neo4j.collection.primitive.PrimitiveArrays;
import org.neo4j.helpers.collection.Iterables;
import org.neo4j.kernel.api.index.IndexEntryUpdate;
import org.neo4j.kernel.api.properties.DefinedProperty;
Expand Down Expand Up @@ -133,12 +133,12 @@ public final long getNodeId()

public long[] labelsChanged()
{
return PrimitiveSortedArraySet.symmetricDifference( labelsBefore, labelsAfter );
return PrimitiveArrays.symmetricDifference( labelsBefore, labelsAfter );
}

public long[] labelsUnchanged()
{
return PrimitiveSortedArraySet.intersect( labelsBefore, labelsAfter );
return PrimitiveArrays.intersect( labelsBefore, labelsAfter );
}

public PrimitiveIntCollection propertiesChanged()
Expand Down
Expand Up @@ -22,15 +22,14 @@
import java.util.Arrays;

/**
* Specialized methods for operations on sets represented as sorted primitive arrays.
* Specialized methods for operations on primitive arrays.
*
* This class does not contain a complete set of operations for all primitives, but only
* the ones that were needed. Feel free to add specializations on demand, but remember to test.
* For set operations (union, intersect, symmetricDifference), input and output arrays
* are arrays containing unique values in sorted ascending order.
*/
public class PrimitiveSortedArraySet
public class PrimitiveArrays
{
private static final long[] NO_LONGS = new long[]{};
private static final int INT_BITS = Integer.BYTES * 8;
private static final long[] EMPTY_LONG_ARRAY = new long[]{};

/**
* Compute union of two sets of integers represented as sorted arrays.
Expand All @@ -50,6 +49,7 @@ public static int[] union( int[] lhs, int[] rhs )
return lhs == null ? rhs : lhs;
}

assert isSortedSet( lhs ) && isSortedSet( rhs );
if ( lhs.length < rhs.length )
{
return union( rhs, lhs );
Expand Down Expand Up @@ -123,17 +123,19 @@ public static long[] intersect( long[] left, long[] right )
{
if ( left == null || right == null )
{
return NO_LONGS;
return EMPTY_LONG_ARRAY;
}

assert isSortedSet( left ) && isSortedSet( right );

long uniqueCounts = countUnique( left, right );
if ( uniqueCounts == 0 ) // complete intersection
{
return right;
}
if ( right( uniqueCounts ) == right.length || left( uniqueCounts ) == left.length ) // non-intersecting
{
return NO_LONGS;
return EMPTY_LONG_ARRAY;
}

long[] intersect = new long[left.length - left( uniqueCounts )];
Expand Down Expand Up @@ -175,10 +177,12 @@ public static long[] symmetricDifference( long[] left, long[] right )
return left == null ? right : left;
}

assert isSortedSet( left ) && isSortedSet( right );

long uniqueCounts = countUnique( left, right );
if ( uniqueCounts == 0 ) // complete intersection
{
return NO_LONGS;
return EMPTY_LONG_ARRAY;
}

long[] difference = new long[left( uniqueCounts ) + right( uniqueCounts )];
Expand Down Expand Up @@ -256,20 +260,38 @@ else if ( left[l] < right[r] )

private static long intPair( int left, int right )
{
return ( ((long)left) << INT_BITS ) | right;
return ( ((long)left) << Integer.SIZE ) | right;
}

private static int left( long pair )
{
return (int)(pair >> INT_BITS);
return (int)(pair >> Integer.SIZE);
}

private static int right( long pair )
{
return (int)(pair & 0xFFFF_FFFFL);
}

private PrimitiveSortedArraySet()
private static boolean isSortedSet( int[] set )
{
for ( int i = 0; i < set.length - 1; i++ )
{
assert set[i] < set[i+1] : "Array is not a sorted set: has " + set[i] + " before " + set[i + 1];
}
return true;
}

private static boolean isSortedSet( long[] set )
{
for ( int i = 0; i < set.length - 1; i++ )
{
assert set[i] < set[i+1] : "Array is not a sorted set: has " + set[i] + " before " + set[i + 1];
}
return true;
}

private PrimitiveArrays()
{ // No instances allowed
}
}
Expand Up @@ -28,7 +28,7 @@
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.nullValue;

public class PrimitiveSortedArraySetTest
public class PrimitiveArraysTest
{
private static final int[] NO_INTS = new int[0];
private static final int[] ONE_INT = new int[]{1};
Expand All @@ -40,53 +40,53 @@ public class PrimitiveSortedArraySetTest
@Test
public void union_shouldHandleNullInput()
{
assertThat( PrimitiveSortedArraySet.union( null, null ), nullValue() );
assertThat( PrimitiveSortedArraySet.union( null, NO_INTS ), equalTo( NO_INTS ) );
assertThat( PrimitiveSortedArraySet.union( NO_INTS, null ), equalTo( NO_INTS ) );
assertThat( PrimitiveSortedArraySet.union( null, ONE_INT ), equalTo( ONE_INT ) );
assertThat( PrimitiveSortedArraySet.union( ONE_INT, null ), equalTo( ONE_INT ) );
assertThat( PrimitiveArrays.union( null, null ), nullValue() );
assertThat( PrimitiveArrays.union( null, NO_INTS ), equalTo( NO_INTS ) );
assertThat( PrimitiveArrays.union( NO_INTS, null ), equalTo( NO_INTS ) );
assertThat( PrimitiveArrays.union( null, ONE_INT ), equalTo( ONE_INT ) );
assertThat( PrimitiveArrays.union( ONE_INT, null ), equalTo( ONE_INT ) );
}

// intersect()

@Test
public void intersect_shouldHandleNullInput()
{
assertThat( PrimitiveSortedArraySet.intersect( null, null ), equalTo( NO_LONGS ) );
assertThat( PrimitiveSortedArraySet.intersect( null, NO_LONGS ), equalTo( NO_LONGS ) );
assertThat( PrimitiveSortedArraySet.intersect( NO_LONGS, null ), equalTo( NO_LONGS ) );
assertThat( PrimitiveSortedArraySet.intersect( null, ONE_LONG ), equalTo( NO_LONGS ) );
assertThat( PrimitiveSortedArraySet.intersect( ONE_LONG, null ), equalTo( NO_LONGS ) );
assertThat( PrimitiveArrays.intersect( null, null ), equalTo( NO_LONGS ) );
assertThat( PrimitiveArrays.intersect( null, NO_LONGS ), equalTo( NO_LONGS ) );
assertThat( PrimitiveArrays.intersect( NO_LONGS, null ), equalTo( NO_LONGS ) );
assertThat( PrimitiveArrays.intersect( null, ONE_LONG ), equalTo( NO_LONGS ) );
assertThat( PrimitiveArrays.intersect( ONE_LONG, null ), equalTo( NO_LONGS ) );
}

@Test
public void intersect_shouldHandleNonIntersectingArrays()
{
assertThat( PrimitiveSortedArraySet.intersect( new long[]{1, 2, 3}, new long[]{4, 5, 6} ),
assertThat( PrimitiveArrays.intersect( new long[]{1, 2, 3}, new long[]{4, 5, 6} ),
equalTo( NO_LONGS ) );

assertThat( PrimitiveSortedArraySet.intersect( new long[]{14, 15, 16}, new long[]{1, 2, 3} ),
assertThat( PrimitiveArrays.intersect( new long[]{14, 15, 16}, new long[]{1, 2, 3} ),
equalTo( NO_LONGS ) );
}

@Test
public void intersect_shouldHandleIntersectingArrays()
{
assertThat( PrimitiveSortedArraySet.intersect( new long[]{1, 2, 3}, new long[]{3, 4, 5} ),
assertThat( PrimitiveArrays.intersect( new long[]{1, 2, 3}, new long[]{3, 4, 5} ),
isArray( 3 ) );

assertThat( PrimitiveSortedArraySet.intersect( new long[]{3, 4, 5}, new long[]{1, 2, 3, 4} ),
assertThat( PrimitiveArrays.intersect( new long[]{3, 4, 5}, new long[]{1, 2, 3, 4} ),
isArray( 3, 4 ) );
}

@Test
public void intersect_shouldHandleComplexIntersectingArraysWithGaps()
{
assertThat(
PrimitiveSortedArraySet.intersect( new long[]{4, 6, 9, 11, 12, 15}, new long[]{2, 3, 4, 7, 8, 9, 12, 16, 19} ),
PrimitiveArrays.intersect( new long[]{4, 6, 9, 11, 12, 15}, new long[]{2, 3, 4, 7, 8, 9, 12, 16, 19} ),
isArray( 4, 9, 12 ) );
assertThat(
PrimitiveSortedArraySet.intersect( new long[]{2, 3, 4, 7, 8, 9, 12, 16, 19}, new long[]{4, 6, 9, 11, 12, 15} ),
PrimitiveArrays.intersect( new long[]{2, 3, 4, 7, 8, 9, 12, 16, 19}, new long[]{4, 6, 9, 11, 12, 15} ),
isArray( 4, 9, 12 ) );
}

Expand All @@ -95,41 +95,43 @@ public void intersect_shouldHandleComplexIntersectingArraysWithGaps()
@Test
public void symDiff_shouldHandleNullInput()
{
assertThat( PrimitiveSortedArraySet.symmetricDifference( null, null ), equalTo( null ) );
assertThat( PrimitiveSortedArraySet.symmetricDifference( null, NO_LONGS ), equalTo( NO_LONGS ) );
assertThat( PrimitiveSortedArraySet.symmetricDifference( NO_LONGS, null ), equalTo( NO_LONGS ) );
assertThat( PrimitiveSortedArraySet.symmetricDifference( null, ONE_LONG ), equalTo( ONE_LONG ) );
assertThat( PrimitiveSortedArraySet.symmetricDifference( ONE_LONG, null ), equalTo( ONE_LONG ) );
assertThat( PrimitiveArrays.symmetricDifference( null, null ), equalTo( null ) );
assertThat( PrimitiveArrays.symmetricDifference( null, NO_LONGS ), equalTo( NO_LONGS ) );
assertThat( PrimitiveArrays.symmetricDifference( NO_LONGS, null ), equalTo( NO_LONGS ) );
assertThat( PrimitiveArrays.symmetricDifference( null, ONE_LONG ), equalTo( ONE_LONG ) );
assertThat( PrimitiveArrays.symmetricDifference( ONE_LONG, null ), equalTo( ONE_LONG ) );
}

@Test
public void symDiff_shouldHandleNonIntersectingArrays()
{
assertThat( PrimitiveSortedArraySet.symmetricDifference( new long[]{1, 2, 3}, new long[]{4, 5, 6} ),
assertThat( PrimitiveArrays.symmetricDifference( new long[]{1, 2, 3}, new long[]{4, 5, 6} ),
isArray( 1, 2, 3, 4, 5, 6 ) );

assertThat( PrimitiveSortedArraySet.symmetricDifference( new long[]{14, 15, 16}, new long[]{1, 2, 3} ),
assertThat( PrimitiveArrays.symmetricDifference( new long[]{14, 15, 16}, new long[]{1, 2, 3} ),
isArray( 1, 2, 3, 14, 15, 16 ) );
}

@Test
public void symDiff_shouldHandleIntersectingArrays()
{
assertThat( PrimitiveSortedArraySet.symmetricDifference( new long[]{1, 2, 3}, new long[]{3, 4, 5} ),
assertThat( PrimitiveArrays.symmetricDifference( new long[]{1, 2, 3}, new long[]{3, 4, 5} ),
isArray( 1, 2, 4, 5 ) );

assertThat( PrimitiveSortedArraySet.symmetricDifference( new long[]{3, 4, 5}, new long[]{1, 2, 3, 4} ),
assertThat( PrimitiveArrays.symmetricDifference( new long[]{3, 4, 5}, new long[]{1, 2, 3, 4} ),
isArray( 1, 2, 5 ) );
}

@Test
public void symDiff_shouldHandleComplexIntersectingArraysWithGaps()
{
assertThat(
PrimitiveSortedArraySet.symmetricDifference( new long[]{4, 6, 9, 11, 12, 15}, new long[]{2, 3, 4, 7, 8, 9, 12, 16, 19} ),
PrimitiveArrays
.symmetricDifference( new long[]{4, 6, 9, 11, 12, 15}, new long[]{2, 3, 4, 7, 8, 9, 12, 16, 19} ),
isArray( 2, 3, 6, 7, 8, 11, 15, 16, 19 ) );
assertThat(
PrimitiveSortedArraySet.symmetricDifference( new long[]{2, 3, 4, 7, 8, 9, 12, 16, 19}, new long[]{4, 6, 9, 11, 12, 15} ),
PrimitiveArrays
.symmetricDifference( new long[]{2, 3, 4, 7, 8, 9, 12, 16, 19}, new long[]{4, 6, 9, 11, 12, 15} ),
isArray( 2, 3, 6, 7, 8, 11, 15, 16, 19 ) );
}

Expand All @@ -139,39 +141,39 @@ public void symDiff_shouldHandleComplexIntersectingArraysWithGaps()
public void shouldCountUnique()
{
assertThat(
PrimitiveSortedArraySet.countUnique( new long[]{1, 2, 3}, new long[]{4, 5, 6} ),
PrimitiveArrays.countUnique( new long[]{1, 2, 3}, new long[]{4, 5, 6} ),
isIntPair( 3, 3 ) );

assertThat(
PrimitiveSortedArraySet.countUnique( new long[]{1, 2, 3}, new long[]{3, 6} ),
PrimitiveArrays.countUnique( new long[]{1, 2, 3}, new long[]{3, 6} ),
isIntPair( 2, 1 ) );

assertThat(
PrimitiveSortedArraySet.countUnique( new long[]{1, 2, 3}, new long[]{3} ),
PrimitiveArrays.countUnique( new long[]{1, 2, 3}, new long[]{3} ),
isIntPair( 2, 0 ) );

assertThat(
PrimitiveSortedArraySet.countUnique( new long[]{3}, new long[]{1, 2, 3} ),
PrimitiveArrays.countUnique( new long[]{3}, new long[]{1, 2, 3} ),
isIntPair( 0, 2 ) );

assertThat(
PrimitiveSortedArraySet.countUnique( new long[]{3}, new long[]{3} ),
PrimitiveArrays.countUnique( new long[]{3}, new long[]{3} ),
isIntPair( 0, 0 ) );

assertThat(
PrimitiveSortedArraySet.countUnique( new long[]{3, 6, 8}, new long[]{} ),
PrimitiveArrays.countUnique( new long[]{3, 6, 8}, new long[]{} ),
isIntPair( 3, 0 ) );

assertThat(
PrimitiveSortedArraySet.countUnique( new long[]{}, new long[]{3, 6, 8} ),
PrimitiveArrays.countUnique( new long[]{}, new long[]{3, 6, 8} ),
isIntPair( 0, 3 ) );

assertThat(
PrimitiveSortedArraySet.countUnique( new long[]{}, new long[]{} ),
PrimitiveArrays.countUnique( new long[]{}, new long[]{} ),
isIntPair( 0, 0 ) );

assertThat(
PrimitiveSortedArraySet.countUnique( new long[]{4, 6, 9, 11, 12, 15}, new long[]{2, 3, 4, 7, 8, 9, 12, 16, 19} ),
PrimitiveArrays.countUnique( new long[]{4, 6, 9, 11, 12, 15}, new long[]{2, 3, 4, 7, 8, 9, 12, 16, 19} ),
isIntPair( 3, 6 ) );
}

Expand Down
Expand Up @@ -27,10 +27,10 @@

import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertSame;
import static org.neo4j.collection.primitive.PrimitiveSortedArraySet.union;
import static org.neo4j.collection.primitive.PrimitiveArrays.union;

@RunWith( Parameterized.class )
public class PrimitiveSortedArraySetUnionTest
public class PrimitiveArraysUnionTest
{
@Parameterized.Parameters( name = "{0}" )
public static Iterable<Object[]> parameters()
Expand All @@ -55,7 +55,7 @@ public static Iterable<Object[]> parameters()
private final int[] rhs;
private final int[] expected;

public PrimitiveSortedArraySetUnionTest( Input input )
public PrimitiveArraysUnionTest( Input input )
{
this.lhs = input.lhs;
this.rhs = input.rhs;
Expand Down
Expand Up @@ -50,7 +50,7 @@

import static java.lang.String.format;
import static java.util.Collections.emptyList;
import static org.neo4j.collection.primitive.PrimitiveSortedArraySet.union;
import static org.neo4j.collection.primitive.PrimitiveArrays.union;
import static org.neo4j.kernel.api.exceptions.schema.ConstraintValidationException.Phase.VALIDATION;

class PropertyExistenceEnforcer
Expand Down

0 comments on commit 7723a60

Please sign in to comment.