├── ALTERNATIVES.txt ├── hppc └── src │ ├── main │ ├── javadoc │ │ └── resources │ │ │ ├── logo.png │ │ │ ├── interfaces.odg │ │ │ ├── interfaces.png │ │ │ ├── tweaks.css │ │ │ └── overview.css │ ├── templates │ │ └── com │ │ │ └── carrotsearch │ │ │ └── hppc │ │ │ ├── procedures │ │ │ ├── KTypeProcedure.java │ │ │ └── KTypeVTypeProcedure.java │ │ │ ├── predicates │ │ │ ├── KTypePredicate.java │ │ │ └── KTypeVTypePredicate.java │ │ │ ├── KTypeLookupContainer.java │ │ │ ├── cursors │ │ │ ├── KTypeCursor.java │ │ │ └── KTypeVTypeCursor.java │ │ │ ├── KTypeSet.java │ │ │ ├── KTypeBufferVisualizer.java │ │ │ ├── KTypeVTypeScatterMap.java │ │ │ ├── KTypeScatterSet.java │ │ │ ├── KTypeCollection.java │ │ │ ├── KTypeIndexedContainer.java │ │ │ ├── KTypeDeque.java │ │ │ ├── AbstractKTypeCollection.java │ │ │ ├── KTypeContainer.java │ │ │ ├── KTypeVTypeIdentityHashMap.java │ │ │ ├── KTypeVTypeAssociativeContainer.java │ │ │ └── KTypeStack.java │ ├── java │ │ └── com │ │ │ └── carrotsearch │ │ │ └── hppc │ │ │ ├── Preallocable.java │ │ │ ├── SuppressForbidden.java │ │ │ ├── RandomizedHashOrderMixer.java │ │ │ ├── BufferAllocationException.java │ │ │ ├── ArraySizingStrategy.java │ │ │ ├── HashOrderMixingStrategy.java │ │ │ ├── XorShift128P.java │ │ │ ├── AbstractIterator.java │ │ │ ├── Containers.java │ │ │ ├── ObjectIdentityHashSet.java │ │ │ ├── BitMixer.java │ │ │ ├── HashContainers.java │ │ │ ├── BoundedProportionalArraySizingStrategy.java │ │ │ ├── BitUtil.java │ │ │ ├── sorting │ │ │ ├── IndirectSort.java │ │ │ └── IndirectComparator.java │ │ │ ├── HashOrderMixing.java │ │ │ └── BitSetIterator.java │ └── assembly │ │ └── bin.xml │ └── test │ ├── templates │ └── com │ │ └── carrotsearch │ │ └── hppc │ │ ├── KTypeScatterSetTest.java │ │ ├── KTypeVTypeScatterMapTest.java │ │ ├── AbstractKTypeTest.java │ │ └── KTypeStackTest.java │ └── java │ └── com │ └── carrotsearch │ └── hppc │ ├── annotations │ └── AwaitsFix.java │ ├── ObjectIntHashMapRegressionTest.java │ ├── TightRandomResizingStrategy.java │ ├── RequireAssertionsRule.java │ ├── StringConversionsTest.java │ ├── ContainersTest.java │ ├── EntryShiftingOnRemovalTest.java │ ├── BoundedProportionalArraySizingStrategyTest.java │ ├── IdentitySetsTest.java │ ├── HashContainersTest.java │ ├── AbstractIteratorTest.java │ ├── IdentityMapsTest.java │ ├── NaNCornerCaseTest.java │ └── HashCollisionsClusteringTest.java ├── etc ├── eclipse │ ├── settings │ │ └── org.eclipse.m2e.core.prefs │ ├── configs │ │ ├── hppc │ │ │ ├── _project │ │ │ └── _externalToolBuilders │ │ │ │ └── hppc.templates-generate.launch │ │ └── hppc-benchmarks │ │ │ ├── _project │ │ │ └── _externalToolBuilders │ │ │ └── hppc.benchmarks-jmh.launch │ ├── hppc.test-all.launch │ ├── hppc.test-templates.launch │ └── hppc.process-templates.launch └── forbidden-apis │ ├── intrinsics.txt │ └── time-relative.txt ├── hppc-benchmarks ├── src │ └── main │ │ └── java │ │ └── com │ │ └── carrotsearch │ │ └── hppc │ │ └── benchmarks │ │ ├── BenchmarkDelegate.java │ │ ├── IntSetOps.java │ │ ├── HppcBenchmarkDelegate.java │ │ ├── implementations │ │ ├── HppcIntSetOps.java │ │ ├── HppcIntScatterSetOps.java │ │ ├── FastutilIntSetOps.java │ │ └── KolobokeIntSetOps.java │ │ ├── B001_ModXor.java │ │ ├── Library.java │ │ ├── B004_HashSet_CollisionAvalanche.java │ │ ├── B003_HashSet_Contains.java │ │ └── B002_HashSet_Add.java └── pom.xml ├── hppc-template-processor ├── src │ ├── test │ │ └── java │ │ │ └── com │ │ │ └── carrotsearch │ │ │ └── hppc │ │ │ └── generator │ │ │ └── parser │ │ │ ├── subpackage │ │ │ └── KTypeVTypeInterfaceImported.java │ │ │ └── KTypeVTypeClass.java │ └── main │ │ └── java │ │ └── com │ │ └── carrotsearch │ │ └── hppc │ │ ├── generator │ │ ├── OutputFile.java │ │ ├── parser │ │ │ ├── Channels.java │ │ │ ├── Replacement.java │ │ │ └── SignatureProcessor.java │ │ ├── TemplateFile.java │ │ ├── IntrinsicMethod.java │ │ ├── Type.java │ │ ├── intrinsics │ │ │ ├── Add.java │ │ │ ├── NewArray.java │ │ │ ├── IsEmpty.java │ │ │ ├── Empty.java │ │ │ ├── Cast.java │ │ │ ├── Equals.java │ │ │ └── AbstractIntrinsicMethod.java │ │ ├── AddSourceMojo.java │ │ ├── AddTestSourceMojo.java │ │ └── TemplateOptions.java │ │ └── Intrinsics.java └── pom.xml ├── NOTICE.txt ├── .gitignore ├── hppc-examples ├── src │ └── test │ │ └── java │ │ └── com │ │ └── carrotsearch │ │ └── hppc │ │ └── examples │ │ ├── Helpers.java │ │ ├── HppcExample_005_IteratingOverObjectBuffers.java │ │ ├── HppcExample_005_ForEachValues.java │ │ ├── HppcExample_001_IteratingOverLists.java │ │ ├── HppcExample_002_IteratingOverDeques.java │ │ ├── HppcExample_003_IteratingOverSets.java │ │ └── HppcExample_004_IteratingOverMaps.java └── pom.xml ├── README.txt └── INSTALL.txt /ALTERNATIVES.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/biubiu/hppc/master/ALTERNATIVES.txt -------------------------------------------------------------------------------- /hppc/src/main/javadoc/resources/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/biubiu/hppc/master/hppc/src/main/javadoc/resources/logo.png -------------------------------------------------------------------------------- /hppc/src/main/javadoc/resources/interfaces.odg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/biubiu/hppc/master/hppc/src/main/javadoc/resources/interfaces.odg -------------------------------------------------------------------------------- /hppc/src/main/javadoc/resources/interfaces.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/biubiu/hppc/master/hppc/src/main/javadoc/resources/interfaces.png -------------------------------------------------------------------------------- /etc/eclipse/settings/org.eclipse.m2e.core.prefs: -------------------------------------------------------------------------------- 1 | activeProfiles=eclipse 2 | eclipse.preferences.version=1 3 | resolveWorkspaceProjects=true 4 | version=1 5 | -------------------------------------------------------------------------------- /etc/forbidden-apis/intrinsics.txt: -------------------------------------------------------------------------------- 1 | @defaultMessage Left-over intrinsics that should have been replaced by the template processor? 2 | com.carrotsearch.hppc.Intrinsics -------------------------------------------------------------------------------- /etc/forbidden-apis/time-relative.txt: -------------------------------------------------------------------------------- 1 | @defaultMessage Time-derived randomness shouldn't be present in the code. 2 | java.lang.System#currentTimeMillis() 3 | java.lang.System#nanoTime() -------------------------------------------------------------------------------- /hppc-benchmarks/src/main/java/com/carrotsearch/hppc/benchmarks/BenchmarkDelegate.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc.benchmarks; 2 | 3 | public interface BenchmarkDelegate{ 4 | T newInstance(); 5 | } 6 | -------------------------------------------------------------------------------- /hppc-template-processor/src/test/java/com/carrotsearch/hppc/generator/parser/subpackage/KTypeVTypeInterfaceImported.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc.generator.parser.subpackage; 2 | 3 | public interface KTypeVTypeInterfaceImported { 4 | } 5 | -------------------------------------------------------------------------------- /hppc-benchmarks/src/main/java/com/carrotsearch/hppc/benchmarks/IntSetOps.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc.benchmarks; 2 | 3 | public interface IntSetOps { 4 | void add(int key); 5 | 6 | void bulkAdd(int [] keys); 7 | int bulkContains(int [] keys); 8 | 9 | int[] iterationOrderArray(); 10 | } 11 | -------------------------------------------------------------------------------- /NOTICE.txt: -------------------------------------------------------------------------------- 1 | ACKNOWLEDGEMENT 2 | =============== 3 | 4 | HPPC borrowed code, ideas or both from: 5 | 6 | * Apache Lucene, http://lucene.apache.org/ 7 | (Apache license) 8 | * Fastutil, http://fastutil.di.unimi.it/ 9 | (Apache license) 10 | * Koloboke, https://github.com/OpenHFT/Koloboke 11 | (Apache license) 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Mac specific 2 | .DS_Store 3 | 4 | # Maven 5 | target 6 | *.versionsBackup 7 | 8 | # Eclipse 9 | .classpath 10 | .project 11 | .settings 12 | .externalToolBuilders 13 | 14 | # External tools. 15 | .clover 16 | 17 | # Locally generated 18 | .builder.classpath 19 | .benchmark.*.db 20 | 21 | # IntelliJ 22 | .idea/ 23 | *.iml -------------------------------------------------------------------------------- /hppc/src/main/templates/com/carrotsearch/hppc/procedures/KTypeProcedure.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc.procedures; 2 | 3 | /** 4 | * A procedure that applies to KType objects. 5 | */ 6 | /*! ${TemplateOptions.generatedAnnotation} !*/ 7 | public interface KTypeProcedure { 8 | public void apply(KType value); 9 | } 10 | -------------------------------------------------------------------------------- /hppc/src/main/templates/com/carrotsearch/hppc/predicates/KTypePredicate.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc.predicates; 2 | 3 | /** 4 | * A predicate that applies to KType objects. 5 | */ 6 | /*! ${TemplateOptions.generatedAnnotation} !*/ 7 | public interface KTypePredicate { 8 | public boolean apply(KType value); 9 | } 10 | -------------------------------------------------------------------------------- /hppc-template-processor/src/main/java/com/carrotsearch/hppc/generator/OutputFile.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc.generator; 2 | 3 | import java.nio.file.Path; 4 | 5 | class OutputFile { 6 | public final Path path; 7 | public boolean upToDate; 8 | 9 | public OutputFile(Path target) { 10 | this.path = target.toAbsolutePath().normalize(); 11 | } 12 | } -------------------------------------------------------------------------------- /hppc-template-processor/src/main/java/com/carrotsearch/hppc/generator/parser/Channels.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc.generator.parser; 2 | 3 | class Channels { 4 | private Channels() {} 5 | 6 | public final static int LINE_COMMENT = 1000; 7 | public final static int BLOCK_COMMENT = 1001; 8 | public final static int JAVADOC_COMMENT = 1002; 9 | } 10 | -------------------------------------------------------------------------------- /hppc-benchmarks/src/main/java/com/carrotsearch/hppc/benchmarks/HppcBenchmarkDelegate.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc.benchmarks; 2 | 3 | public class HppcBenchmarkDelegate 4 | implements B002_HashSet_Add.Ops 5 | { 6 | public HppcBenchmarkDelegate() { 7 | } 8 | 9 | @Override 10 | public Object addAll(int[] keys) { 11 | return null; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /hppc/src/main/templates/com/carrotsearch/hppc/procedures/KTypeVTypeProcedure.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc.procedures; 2 | 3 | /** 4 | * A procedure that applies to KType, VType pairs. 5 | */ 6 | /*! ${TemplateOptions.generatedAnnotation} !*/ 7 | public interface KTypeVTypeProcedure { 8 | public void apply(KType key, VType value); 9 | } 10 | -------------------------------------------------------------------------------- /hppc/src/main/templates/com/carrotsearch/hppc/predicates/KTypeVTypePredicate.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc.predicates; 2 | 3 | /** 4 | * A predicate that applies to KType, VType pairs. 5 | */ 6 | /*! ${TemplateOptions.generatedAnnotation} !*/ 7 | public interface KTypeVTypePredicate { 8 | public boolean apply(KType key, VType value); 9 | } 10 | -------------------------------------------------------------------------------- /hppc-template-processor/src/main/java/com/carrotsearch/hppc/generator/TemplateFile.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc.generator; 2 | 3 | import java.nio.file.Path; 4 | 5 | class TemplateFile { 6 | public final Path path; 7 | 8 | public TemplateFile(Path path) { 9 | this.path = path; 10 | } 11 | 12 | public String getFileName() { 13 | return path.getFileName().toString(); 14 | } 15 | } -------------------------------------------------------------------------------- /hppc-template-processor/src/main/java/com/carrotsearch/hppc/generator/IntrinsicMethod.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc.generator; 2 | 3 | import java.util.ArrayList; 4 | import java.util.regex.Matcher; 5 | 6 | /** 7 | * Intrinsic method invocation. 8 | */ 9 | public interface IntrinsicMethod { 10 | void invoke(Matcher m, StringBuilder sb, TemplateOptions templateOptions, String genericCast, ArrayList params); 11 | } 12 | -------------------------------------------------------------------------------- /hppc/src/main/javadoc/resources/tweaks.css: -------------------------------------------------------------------------------- 1 | 2 | a.logo { 3 | float: right; 4 | padding-left: 10px; 5 | position: relative; 6 | width: 82px; 7 | height: 35px; 8 | background: url('logo.png'); 9 | background-repeat: no-repeat; 10 | background-position: right top; 11 | } 12 | 13 | /* Page background color */ 14 | body { 15 | font-family: Trebuchet MS, Arial; 16 | background-color: white; 17 | font-size: 10pt; 18 | } 19 | 20 | -------------------------------------------------------------------------------- /hppc/src/test/templates/com/carrotsearch/hppc/KTypeScatterSetTest.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc; 2 | 3 | import org.junit.Before; 4 | 5 | /** 6 | * Unit tests for {@link KTypeHashSet}. 7 | */ 8 | /*! ${TemplateOptions.generatedAnnotation} !*/ 9 | public class KTypeScatterSetTest extends KTypeHashSetTest 10 | { 11 | /* */ 12 | @Before 13 | public void initialize() 14 | { 15 | set = new KTypeScatterSet<>(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /hppc/src/main/templates/com/carrotsearch/hppc/KTypeLookupContainer.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc; 2 | 3 | /** 4 | * Marker interface for containers that can check if they contain a given object 5 | * in at least time O(log n) and ideally in amortized constant time 6 | * O(1). 7 | */ 8 | /*! ${TemplateOptions.generatedAnnotation} !*/ 9 | public interface KTypeLookupContainer extends KTypeContainer { 10 | public boolean contains(KType e); 11 | } 12 | -------------------------------------------------------------------------------- /hppc/src/main/java/com/carrotsearch/hppc/Preallocable.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc; 2 | 3 | /** 4 | * Anything that can preallocate buffers given prior knowledge of the number of 5 | * stored elements. 6 | */ 7 | public interface Preallocable { 8 | /** 9 | * Ensure this container can hold at least the given number of elements 10 | * without resizing its buffers. 11 | * 12 | * @param expectedElements 13 | * The total number of elements, inclusive. 14 | */ 15 | public void ensureCapacity(int expectedElements); 16 | } 17 | -------------------------------------------------------------------------------- /hppc/src/main/java/com/carrotsearch/hppc/SuppressForbidden.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * Suppresses forbidden-API checks. 10 | */ 11 | @Retention(RetentionPolicy.CLASS) 12 | @Target({ 13 | ElementType.CONSTRUCTOR, 14 | ElementType.FIELD, 15 | ElementType.METHOD, 16 | ElementType.TYPE }) 17 | public @interface SuppressForbidden { 18 | } 19 | -------------------------------------------------------------------------------- /hppc-examples/src/test/java/com/carrotsearch/hppc/examples/Helpers.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc.examples; 2 | 3 | import java.util.Locale; 4 | 5 | import com.carrotsearch.hppc.SuppressForbidden; 6 | 7 | class Helpers { 8 | @SuppressForbidden 9 | public static void printf(String msg, Object... args) { 10 | System.out.printf(Locale.ROOT, msg, args); 11 | } 12 | 13 | @SuppressForbidden 14 | public static void printfln(String msg, Object... args) { 15 | System.out.printf(Locale.ROOT, msg, args); 16 | System.out.println(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /hppc/src/test/templates/com/carrotsearch/hppc/KTypeVTypeScatterMapTest.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc; 2 | 3 | import org.junit.Ignore; 4 | 5 | 6 | /** 7 | * Tests for {@link KTypeVTypeHashMap}. 8 | */ 9 | /* ! ${TemplateOptions.generatedAnnotation} ! */ 10 | public class KTypeVTypeScatterMapTest extends KTypeVTypeHashMapTest 11 | { 12 | @Override 13 | protected KTypeVTypeHashMap newInstance() { 14 | return new KTypeVTypeScatterMap<>(); 15 | } 16 | 17 | @Override @Ignore 18 | public void testEqualsSameClass() { 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /hppc/src/test/java/com/carrotsearch/hppc/annotations/AwaitsFix.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc.annotations; 2 | 3 | import java.lang.annotation.Documented; 4 | import java.lang.annotation.Inherited; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | 8 | import com.carrotsearch.randomizedtesting.annotations.TestGroup; 9 | 10 | /** 11 | * An annotation for bug tracking issues that await resolution. 12 | */ 13 | @Documented 14 | @Inherited 15 | @Retention(RetentionPolicy.RUNTIME) 16 | @TestGroup(enabled = false) 17 | public @interface AwaitsFix { 18 | String value(); 19 | } 20 | -------------------------------------------------------------------------------- /README.txt: -------------------------------------------------------------------------------- 1 | 2 | HPPC: High Performance Primitive Collections 3 | -------------------------------------------- 4 | 5 | Collections of primitive types (maps, sets, stacks, lists) 6 | with open internals and an API twist 7 | (no java.util.collections.* compatibility). 8 | 9 | See the following for more information: 10 | Wiki: https://github.com/carrotsearch/hppc/wiki 11 | Bugs: http://issues.carrot2.org/browse/HPPC/ 12 | 13 | See ALTERNATIVES.txt if you're just shopping around. 14 | 15 | See LICENSE.txt to make your company's lawyer happy. 16 | 17 | See CHANGES.txt for API changes and updates. 18 | 19 | (c) Carrot Search s.c., http://carrotsearch.com/ 20 | -------------------------------------------------------------------------------- /INSTALL.txt: -------------------------------------------------------------------------------- 1 | Maven shortcuts 2 | --------------- 3 | 4 | # All unit tests 5 | mvn clean verify 6 | 7 | # Package JAR files, no tests. 8 | mvn clean package -Pquick 9 | 10 | 11 | Eclipse workflow/ import 12 | ------------------------ 13 | 14 | # Install template processor and copy over initial IDE .settings 15 | mvn -Peclipse 16 | 17 | # Ready to use m2e: "File->Import->Existing Maven Projects". 18 | 19 | 20 | Benchmarking 21 | ------------ 22 | 23 | There are some sanity tests and isolated benchmarks 24 | of common operations in hppc-benchmarks. 25 | 26 | # Create benchmark JAR 27 | mvn package -Pquick -am -pl :hppc-benchmarks 28 | 29 | # List available benchmarks 30 | java -jar hppc-benchmarks/target/benchmarks.jar -l 31 | -------------------------------------------------------------------------------- /hppc/src/test/java/com/carrotsearch/hppc/ObjectIntHashMapRegressionTest.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc; 2 | 3 | import static org.junit.Assert.*; 4 | 5 | import org.junit.Test; 6 | 7 | public class ObjectIntHashMapRegressionTest 8 | { 9 | /** @see "http://issues.carrot2.org/browse/HPPC-32" */ 10 | @Test 11 | public void testEqualsOnObjectKeys() 12 | { 13 | ObjectIntHashMap map = new ObjectIntHashMap(); 14 | String key1 = "key1"; 15 | String key2 = new String("key1"); 16 | 17 | map.put(key1, 1); 18 | assertEquals(1, map.get(key2)); 19 | assertEquals(1, map.put(key2, 2)); 20 | assertEquals(1, map.size()); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /hppc/src/main/templates/com/carrotsearch/hppc/cursors/KTypeCursor.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc.cursors; 2 | 3 | /** 4 | * A cursor over a collection of KTypes. 5 | */ 6 | /*! ${TemplateOptions.generatedAnnotation} !*/ 7 | public final class KTypeCursor { 8 | /** 9 | * The current value's index in the container this cursor belongs to. The 10 | * meaning of this index is defined by the container (usually it will be an 11 | * index in the underlying storage buffer). 12 | */ 13 | public int index; 14 | 15 | /** 16 | * The current value. 17 | */ 18 | public KType value; 19 | 20 | @Override 21 | public String toString() { 22 | return "[cursor, index: " + index + ", value: " + value + "]"; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /hppc-template-processor/src/main/java/com/carrotsearch/hppc/generator/parser/Replacement.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc.generator.parser; 2 | 3 | import org.antlr.v4.runtime.misc.Interval; 4 | import org.antlr.v4.runtime.tree.SyntaxTree; 5 | 6 | /** */ 7 | final class Replacement { 8 | public final Interval interval; 9 | public final String replacement; 10 | 11 | public Replacement(Interval interval, String replacement) { 12 | this.interval = interval; 13 | this.replacement = replacement; 14 | } 15 | 16 | public Replacement(SyntaxTree ctx, String replacement) { 17 | this(ctx.getSourceInterval(), replacement); 18 | } 19 | 20 | @Override 21 | public String toString() { 22 | return interval + " => " + replacement; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /hppc-template-processor/src/main/java/com/carrotsearch/hppc/generator/Type.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc.generator; 2 | 3 | import java.util.Locale; 4 | 5 | public enum Type { 6 | GENERIC, 7 | BYTE, 8 | CHAR, 9 | SHORT, 10 | INT, 11 | FLOAT, 12 | LONG, 13 | DOUBLE; 14 | 15 | public String getBoxedType() { 16 | if (this == GENERIC) { 17 | return "Object"; 18 | } else { 19 | String boxed = name().toLowerCase(); 20 | return Character.toUpperCase(boxed.charAt(0)) + boxed.substring(1); 21 | } 22 | } 23 | 24 | public String getType() { 25 | if (this == GENERIC) { 26 | return "Object"; 27 | } else { 28 | return name().toLowerCase(Locale.ROOT); 29 | } 30 | } 31 | 32 | public boolean isGeneric() { 33 | return this == GENERIC; 34 | } 35 | } -------------------------------------------------------------------------------- /hppc-template-processor/src/main/java/com/carrotsearch/hppc/generator/intrinsics/Add.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc.generator.intrinsics; 2 | 3 | import java.util.ArrayList; 4 | import java.util.regex.Matcher; 5 | 6 | import com.carrotsearch.hppc.generator.TemplateOptions; 7 | import com.carrotsearch.hppc.generator.Type; 8 | 9 | public class Add extends AbstractIntrinsicMethod { 10 | @Override 11 | public void invoke(Matcher m, StringBuilder sb, TemplateOptions templateOptions, String genericCast, ArrayList params) { 12 | expectArgumentCount(m, params, 2); 13 | 14 | Type type = inferTemplateType(m, templateOptions, genericCast); 15 | if (type.isGeneric()) { 16 | throw new RuntimeException("Can't add generic types: " + m.group()); 17 | } 18 | 19 | sb.append(String.format("((%1$s) + (%2$s))", params.toArray())); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /hppc/src/main/templates/com/carrotsearch/hppc/cursors/KTypeVTypeCursor.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc.cursors; 2 | 3 | /** 4 | * A cursor over entries of an associative container (KType keys and VType 5 | * values). 6 | */ 7 | /*! ${TemplateOptions.generatedAnnotation} !*/ 8 | public final class KTypeVTypeCursor { 9 | /** 10 | * The current key and value's index in the container this cursor belongs to. 11 | * The meaning of this index is defined by the container (usually it will be 12 | * an index in the underlying storage buffer). 13 | */ 14 | public int index; 15 | 16 | /** 17 | * The current key. 18 | */ 19 | public KType key; 20 | 21 | /** 22 | * The current value. 23 | */ 24 | public VType value; 25 | 26 | @Override 27 | public String toString() { 28 | return "[cursor, index: " + index + ", key: " + key + ", value: " + value + "]"; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /hppc/src/test/java/com/carrotsearch/hppc/TightRandomResizingStrategy.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc; 2 | 3 | import com.carrotsearch.randomizedtesting.RandomizedContext; 4 | 5 | 6 | public final class TightRandomResizingStrategy implements ArraySizingStrategy { 7 | private final int maxRandomIncrement; 8 | public int growCalls; 9 | 10 | public TightRandomResizingStrategy(int maxRandomIncrement) { 11 | this.maxRandomIncrement = maxRandomIncrement; 12 | } 13 | 14 | public TightRandomResizingStrategy() { 15 | this(10); 16 | } 17 | 18 | @Override 19 | public int grow(int currentBufferLength, int elementsCount, int expectedAdditions) { 20 | growCalls++; 21 | 22 | int r = 0; 23 | if (maxRandomIncrement > 0) { 24 | r += RandomizedContext.current().getRandom().nextInt(maxRandomIncrement); 25 | } 26 | 27 | return Math.max(currentBufferLength, elementsCount + expectedAdditions) + r; 28 | } 29 | } -------------------------------------------------------------------------------- /hppc-template-processor/src/test/java/com/carrotsearch/hppc/generator/parser/KTypeVTypeClass.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc.generator.parser; 2 | 3 | import com.carrotsearch.hppc.generator.parser.subpackage.KTypeVTypeInterfaceImported; 4 | 5 | /** 6 | * A list of KTypes. 7 | */ 8 | public class KTypeVTypeClass 9 | extends KTypeVTypeSuper 10 | implements KTypeVTypeInterface, 11 | KTypeVTypeInterfaceImported, 12 | Cloneable 13 | { 14 | KType [] keys; 15 | 16 | public KTypeVTypeClass() {} 17 | public KTypeVTypeClass(KType[] foo, VType boo) {} 18 | 19 | public KTypeVTypeClass(KTypeVTypeSuper foo) {} 20 | public VType foo(KType key, VType value) { throw new RuntimeException(); } 21 | 22 | public void foo(KTypeVTypeSuper foo) {} 23 | } 24 | 25 | class KTypeVTypeSuper {} 26 | interface KTypeVTypeInterface {} -------------------------------------------------------------------------------- /hppc/src/main/java/com/carrotsearch/hppc/RandomizedHashOrderMixer.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc; 2 | 3 | import java.util.concurrent.atomic.AtomicLong; 4 | 5 | /** 6 | * Randomized hash order. Does not guarantee deterministic hash ordering between 7 | * runs. In fact, it tries hard to avoid such guarantee. 8 | */ 9 | public final class RandomizedHashOrderMixer implements HashOrderMixingStrategy { 10 | public final static RandomizedHashOrderMixer INSTANCE = new RandomizedHashOrderMixer(); 11 | 12 | protected final AtomicLong seedMixer; 13 | 14 | public RandomizedHashOrderMixer() { 15 | this(Containers.randomSeed64()); 16 | } 17 | 18 | public RandomizedHashOrderMixer(long seed) { 19 | seedMixer = new AtomicLong(seed); 20 | } 21 | 22 | @Override 23 | public int newKeyMixer(int newContainerBufferSize) { 24 | return (int) BitMixer.mix64(seedMixer.incrementAndGet()); 25 | } 26 | 27 | @Override 28 | public HashOrderMixingStrategy clone() { 29 | return this; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /etc/eclipse/configs/hppc/_project: -------------------------------------------------------------------------------- 1 | 2 | 3 | hppc 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.ui.externaltools.ExternalToolBuilder 10 | auto, 11 | 12 | 13 | LaunchConfigHandle 14 | <project>/.externalToolBuilders/hppc.templates-generate.launch 15 | 16 | 17 | 18 | 19 | org.eclipse.jdt.core.javabuilder 20 | 21 | 22 | 23 | 24 | org.eclipse.m2e.core.maven2Builder 25 | 26 | 27 | 28 | 29 | 30 | org.eclipse.jdt.core.javanature 31 | org.eclipse.m2e.core.maven2Nature 32 | 33 | 34 | -------------------------------------------------------------------------------- /etc/eclipse/configs/hppc-benchmarks/_project: -------------------------------------------------------------------------------- 1 | 2 | 3 | hppc-benchmarks 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.ui.externaltools.ExternalToolBuilder 10 | auto, 11 | 12 | 13 | LaunchConfigHandle 14 | <project>/.externalToolBuilders/hppc.benchmarks-jmh.launch 15 | 16 | 17 | 18 | 19 | org.eclipse.jdt.core.javabuilder 20 | 21 | 22 | 23 | 24 | org.eclipse.m2e.core.maven2Builder 25 | 26 | 27 | 28 | 29 | 30 | org.eclipse.jdt.core.javanature 31 | org.eclipse.m2e.core.maven2Nature 32 | 33 | 34 | -------------------------------------------------------------------------------- /hppc/src/test/java/com/carrotsearch/hppc/RequireAssertionsRule.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc; 2 | 3 | import static org.junit.Assert.assertTrue; 4 | 5 | import org.junit.Before; 6 | import org.junit.rules.MethodRule; 7 | import org.junit.runners.model.FrameworkMethod; 8 | import org.junit.runners.model.Statement; 9 | 10 | /** 11 | * A JUnit rule that forces assertions to be enabled. 12 | */ 13 | public class RequireAssertionsRule implements MethodRule 14 | { 15 | public Statement apply(Statement base, 16 | FrameworkMethod paramFrameworkMethod, Object paramObject) 17 | { 18 | checkAssertionsEnabled(); 19 | return base; 20 | } 21 | 22 | /* */ 23 | @Before 24 | public void checkAssertionsEnabled() 25 | { 26 | boolean enabled = true; 27 | try 28 | { 29 | assert false; 30 | enabled = false; 31 | } 32 | catch (AssertionError e) 33 | { 34 | // Expected, fall through. 35 | } 36 | 37 | assertTrue("Enable JVM assertions for testing.", enabled); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /hppc-benchmarks/src/main/java/com/carrotsearch/hppc/benchmarks/implementations/HppcIntSetOps.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc.benchmarks.implementations; 2 | 3 | import com.carrotsearch.hppc.IntHashSet; 4 | import com.carrotsearch.hppc.benchmarks.IntSetOps; 5 | 6 | public class HppcIntSetOps implements IntSetOps { 7 | private final IntHashSet delegate; 8 | 9 | public HppcIntSetOps(int expectedElements, double loadFactor) { 10 | this.delegate = new IntHashSet(expectedElements, loadFactor); 11 | } 12 | 13 | @Override 14 | public void add(int key) { 15 | delegate.add(key); 16 | } 17 | 18 | @Override 19 | public void bulkAdd(int[] keys) { 20 | for (int key : keys) { 21 | delegate.add(key); 22 | } 23 | } 24 | 25 | @Override 26 | public int bulkContains(int[] keys) { 27 | int v = 0; 28 | for (int key : keys) { 29 | if (delegate.contains(key)) { 30 | v++; 31 | } 32 | } 33 | return v; 34 | } 35 | 36 | @Override 37 | public int[] iterationOrderArray() { 38 | return delegate.toArray(); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /hppc-template-processor/src/main/java/com/carrotsearch/hppc/generator/AddSourceMojo.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc.generator; 2 | 3 | import java.io.File; 4 | 5 | import org.apache.maven.plugin.AbstractMojo; 6 | import org.apache.maven.plugins.annotations.LifecyclePhase; 7 | import org.apache.maven.plugins.annotations.Mojo; 8 | import org.apache.maven.plugins.annotations.Parameter; 9 | import org.apache.maven.project.MavenProject; 10 | 11 | /** 12 | * Adds additional source directories to test or main sources. 13 | */ 14 | @Mojo(name = "add-source", 15 | defaultPhase = LifecyclePhase.GENERATE_SOURCES, 16 | threadSafe = true, 17 | requiresProject = true) 18 | public class AddSourceMojo extends AbstractMojo { 19 | @Parameter( required = true ) 20 | public File[] sources; 21 | 22 | @Parameter(property = "project", 23 | readonly = true, 24 | required = true) 25 | private MavenProject project; 26 | 27 | public void execute() { 28 | for (File source : sources) { 29 | this.project.addCompileSourceRoot(source.getAbsolutePath()); 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /hppc-template-processor/src/main/java/com/carrotsearch/hppc/generator/AddTestSourceMojo.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc.generator; 2 | 3 | import java.io.File; 4 | 5 | import org.apache.maven.plugin.AbstractMojo; 6 | import org.apache.maven.plugins.annotations.LifecyclePhase; 7 | import org.apache.maven.plugins.annotations.Mojo; 8 | import org.apache.maven.plugins.annotations.Parameter; 9 | import org.apache.maven.project.MavenProject; 10 | 11 | /** 12 | * Adds additional source directories to test or main sources. 13 | */ 14 | @Mojo(name = "add-test-source", 15 | defaultPhase = LifecyclePhase.GENERATE_TEST_SOURCES, 16 | threadSafe = true, 17 | requiresProject = true) 18 | public class AddTestSourceMojo extends AbstractMojo { 19 | @Parameter( required = true ) 20 | public File[] sources; 21 | 22 | @Parameter(property = "project", 23 | readonly = true, 24 | required = true) 25 | private MavenProject project; 26 | 27 | public void execute() { 28 | for (File source : sources) { 29 | this.project.addTestCompileSourceRoot(source.getAbsolutePath()); 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /hppc-benchmarks/src/main/java/com/carrotsearch/hppc/benchmarks/implementations/HppcIntScatterSetOps.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc.benchmarks.implementations; 2 | 3 | import com.carrotsearch.hppc.IntScatterSet; 4 | import com.carrotsearch.hppc.benchmarks.*; 5 | 6 | public class HppcIntScatterSetOps implements IntSetOps 7 | { 8 | private final IntScatterSet delegate; 9 | 10 | public HppcIntScatterSetOps(int expectedElements, double loadFactor) { 11 | this.delegate = new IntScatterSet(expectedElements, loadFactor); 12 | } 13 | 14 | @Override 15 | public void add(int key) { 16 | delegate.add(key); 17 | } 18 | 19 | @Override 20 | public void bulkAdd(int[] keys) { 21 | for (int key : keys) { 22 | delegate.add(key); 23 | } 24 | } 25 | 26 | @Override 27 | public int bulkContains(int[] keys) { 28 | int v = 0; 29 | for (int key : keys) { 30 | if (delegate.contains(key)) { 31 | v++; 32 | } 33 | } 34 | return v; 35 | } 36 | 37 | @Override 38 | public int[] iterationOrderArray() { 39 | return delegate.toArray(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /hppc-examples/src/test/java/com/carrotsearch/hppc/examples/HppcExample_005_IteratingOverObjectBuffers.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc.examples; 2 | 3 | import static com.carrotsearch.hppc.examples.Helpers.*; 4 | 5 | import org.junit.Test; 6 | 7 | import com.carrotsearch.hppc.ObjectArrayList; 8 | 9 | /** 10 | * Examples of how to iterate over HPPC lists with object (generic) buffers. 11 | */ 12 | public class HppcExample_005_IteratingOverObjectBuffers { 13 | public final ObjectArrayList list = ObjectArrayList.from(1, 1, 2, 3, 5); 14 | 15 | /** 16 | * Compared to {@link HppcExample_001_IteratingOverLists#directBufferLoop()}, 17 | * a direct buffer access for Object types is a bit trickier because the 18 | * buffer is actually Object[], not an array of the declared generic type. 19 | * 20 | * A manual cast to the generic type (for every element) is required. 21 | */ 22 | @Test 23 | public void directBufferLoop() throws Exception { 24 | final Object[] buffer = list.buffer; 25 | final int size = list.size(); 26 | for (int i = 0; i < size; i++) { 27 | printfln("list[%d] = %d", i, buffer[i]); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /hppc-benchmarks/src/main/java/com/carrotsearch/hppc/benchmarks/implementations/FastutilIntSetOps.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc.benchmarks.implementations; 2 | 3 | import it.unimi.dsi.fastutil.ints.IntOpenHashSet; 4 | 5 | import com.carrotsearch.hppc.benchmarks.IntSetOps; 6 | 7 | public class FastutilIntSetOps implements IntSetOps { 8 | private final IntOpenHashSet delegate; 9 | 10 | public FastutilIntSetOps(int expectedElements, double loadFactor) { 11 | this.delegate = new IntOpenHashSet(expectedElements, (float) loadFactor); 12 | } 13 | 14 | @Override 15 | public void add(int key) { 16 | delegate.add(key); 17 | } 18 | 19 | @Override 20 | public void bulkAdd(int[] keys) { 21 | for (int key : keys) { 22 | delegate.add(key); 23 | } 24 | } 25 | 26 | @Override 27 | public int bulkContains(int[] keys) { 28 | int v = 0; 29 | for (int key : keys) { 30 | if (delegate.contains(key)) { 31 | v++; 32 | } 33 | } 34 | return v; 35 | } 36 | 37 | @Override 38 | public int[] iterationOrderArray() { 39 | return delegate.toIntArray(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /hppc/src/main/java/com/carrotsearch/hppc/BufferAllocationException.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc; 2 | 3 | import java.util.IllegalFormatException; 4 | import java.util.Locale; 5 | 6 | @SuppressWarnings("serial") 7 | public class BufferAllocationException extends RuntimeException { 8 | public BufferAllocationException(String message) { 9 | super(message); 10 | } 11 | 12 | public BufferAllocationException(String message, Object... args) { 13 | this(message, null, args); 14 | } 15 | 16 | public BufferAllocationException(String message, Throwable t, Object... args) { 17 | super(formatMessage(message, t, args), t); 18 | } 19 | 20 | private static String formatMessage(String message, Throwable t, Object... args) { 21 | try { 22 | return String.format(Locale.ROOT, message, args); 23 | } catch (IllegalFormatException e) { 24 | BufferAllocationException substitute = 25 | new BufferAllocationException(message + " [ILLEGAL FORMAT, ARGS SUPPRESSED]"); 26 | if (t != null) { 27 | substitute.addSuppressed(t); 28 | } 29 | substitute.addSuppressed(e); 30 | throw substitute; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /hppc/src/main/templates/com/carrotsearch/hppc/KTypeSet.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc; 2 | 3 | /** 4 | * A set of KTypes. 5 | */ 6 | /*! ${TemplateOptions.generatedAnnotation} !*/ 7 | public interface KTypeSet extends KTypeCollection { 8 | /** 9 | * Adds k to the set. 10 | * 11 | * @return Returns true if this element was not part of the set 12 | * before. Returns false if an equal element is part of 13 | * the set, and replaces the existing equal element with the 14 | * argument (if keys are object types). 15 | */ 16 | public boolean add(KType k); 17 | 18 | /** 19 | * Visually depict the distribution of keys. 20 | * 21 | * @param characters 22 | * The number of characters to "squeeze" the entire buffer into. 23 | * @return Returns a sequence of characters where '.' depicts an empty 24 | * fragment of the internal buffer and 'X' depicts full or nearly full 25 | * capacity within the buffer's range and anything between 1 and 9 is between. 26 | */ 27 | public String visualizeKeyDistribution(int characters); 28 | } 29 | -------------------------------------------------------------------------------- /hppc/src/main/assembly/bin.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | distribution 6 | 7 | 8 | zip 9 | 10 | 11 | 12 | 13 | ../ 14 | 15 | 16 | ALTERNATIVES.txt 17 | CHANGES.txt 18 | LICENSE.txt 19 | NOTICE.txt 20 | README.txt 21 | 22 | 23 | 24 | 25 | ${project.build.directory} 26 | 27 | 28 | *.jar 29 | apidocs/** 30 | 31 | 32 | *-javadoc.jar 33 | *-sources.jar 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /hppc/src/main/java/com/carrotsearch/hppc/ArraySizingStrategy.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc; 2 | 3 | /** 4 | * Resizing (growth) strategy for array-backed buffers. 5 | */ 6 | public interface ArraySizingStrategy { 7 | /** 8 | * @param currentBufferLength 9 | * Current size of the array (buffer). This number should comply with 10 | * the strategy's policies (it is a result of initial rounding or 11 | * further growCalls). It can also be zero, indicating the growth 12 | * from an empty buffer. 13 | * 14 | * @param elementsCount 15 | * Number of elements stored in the buffer. 16 | * 17 | * @param expectedAdditions 18 | * Expected number of additions (resize hint). 19 | * 20 | * @return Must return a new size at least as big as to hold 21 | * elementsCount + expectedAdditions. 22 | * 23 | * @throws BufferAllocationException 24 | * If the sizing strategy cannot grow the buffer (for example due to 25 | * constraints or memory limits). 26 | */ 27 | int grow(int currentBufferLength, int elementsCount, int expectedAdditions) throws BufferAllocationException; 28 | } 29 | -------------------------------------------------------------------------------- /hppc/src/test/java/com/carrotsearch/hppc/StringConversionsTest.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc; 2 | 3 | import static org.junit.Assert.*; 4 | 5 | import org.junit.Test; 6 | 7 | public class StringConversionsTest 8 | { 9 | @Test 10 | public void testByteList() 11 | { 12 | ByteArrayList list = new ByteArrayList(); 13 | list.add(new byte [] {1, 2, 3}); 14 | assertEquals("[1, 2, 3]", list.toString()); 15 | } 16 | 17 | @Test 18 | public void testCharList() 19 | { 20 | CharArrayList list = new CharArrayList(); 21 | list.add(new char [] {'a', 'b', 'c'}); 22 | assertEquals("[a, b, c]", list.toString()); 23 | } 24 | 25 | @Test 26 | public void testObjectList() 27 | { 28 | ObjectArrayList list = new ObjectArrayList(); 29 | list.add("ab", "ac", "ad"); 30 | assertEquals("[ab, ac, ad]", list.toString()); 31 | } 32 | 33 | @Test 34 | public void testObjectObjectMap() 35 | { 36 | ObjectObjectHashMap map = 37 | ObjectObjectHashMap.from( 38 | new String [] {"a"}, 39 | new String [] {"b"}); 40 | 41 | assertEquals("[a=>b]", map.toString()); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /etc/eclipse/hppc.test-all.launch: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /hppc/src/test/java/com/carrotsearch/hppc/ContainersTest.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc; 2 | 3 | import org.assertj.core.api.Assertions; 4 | import org.junit.After; 5 | import org.junit.Rule; 6 | import org.junit.Test; 7 | import org.junit.rules.RuleChain; 8 | import org.junit.rules.TestRule; 9 | 10 | import com.carrotsearch.randomizedtesting.RandomizedTest; 11 | import com.carrotsearch.randomizedtesting.rules.SystemPropertiesRestoreRule; 12 | 13 | /* */ 14 | public class ContainersTest extends RandomizedTest { 15 | @Rule 16 | public final TestRule rules = RuleChain.outerRule( 17 | new SystemPropertiesRestoreRule()); 18 | 19 | @After 20 | public void resetState() { 21 | Containers.test$reset(); 22 | } 23 | 24 | @Test 25 | public void testNoTestsSeed() { 26 | System.clearProperty("tests.seed"); 27 | Containers.test$reset(); 28 | 29 | Assertions.assertThat(Containers.randomSeed64()) 30 | .isNotEqualTo(Containers.randomSeed64()); 31 | } 32 | 33 | @Test 34 | public void testWithTestsSeed() { 35 | System.setProperty("tests.seed", "deadbeef"); 36 | Containers.test$reset(); 37 | 38 | Assertions.assertThat(Containers.randomSeed64()) 39 | .isEqualTo(Containers.randomSeed64()); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /hppc/src/main/java/com/carrotsearch/hppc/HashOrderMixingStrategy.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc; 2 | 3 | /** 4 | * Hash order mixing strategy implementations should provide an, ideally, 5 | * random integer that is later XORed with the hash of a given key before 6 | * the slot lookup in associative arrays. 7 | * 8 | *

9 | * Why good hash mixing is important is explained in the 10 | * differences between hash 11 | * and scatter sets. 12 | *

13 | * 14 | * @see ObjectHashSet#hashKey 15 | * @see ObjectObjectHashMap#hashKey 16 | * 17 | * @see HashOrderMixing 18 | */ 19 | public interface HashOrderMixingStrategy extends Cloneable { 20 | /** 21 | * A new key mixer value. The value can be derived from the new buffer size of the 22 | * container, but preferably should be random and unique. 23 | * 24 | * @param newContainerBufferSize 25 | */ 26 | public int newKeyMixer(int newContainerBufferSize); 27 | 28 | /** 29 | * @return Return a clone of this strategy. This should use a different mixing 30 | * because cloned containers should have a different hash ordering. 31 | */ 32 | public HashOrderMixingStrategy clone(); 33 | } 34 | -------------------------------------------------------------------------------- /hppc-examples/src/test/java/com/carrotsearch/hppc/examples/HppcExample_005_ForEachValues.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc.examples; 2 | 3 | import org.junit.Test; 4 | 5 | import com.carrotsearch.hppc.IntIntHashMap; 6 | import com.carrotsearch.hppc.procedures.IntIntProcedure; 7 | 8 | /** 9 | * An example of plucking a value from an anonymous inner class. 10 | */ 11 | public class HppcExample_005_ForEachValues { 12 | @Test 13 | public void forEach_FilteredCounting() { 14 | // Create a map of key-value pairs. 15 | final IntIntHashMap map = new IntIntHashMap(); 16 | map.put(1, 2); 17 | map.put(2, -5); 18 | map.put(3, 10); 19 | map.put(4, -1); 20 | 21 | // And count only non-negative values. Note the "counter" 22 | // is physically part of the anonymous inner class but we can 23 | // access it because of how forEach is declared (it returns the exact 24 | // subclass type of the argument). 25 | 26 | int count = map.forEach(new IntIntProcedure() { 27 | int counter; 28 | 29 | public void apply(int key, int value) { 30 | if (value >= 0) { 31 | counter++; 32 | } 33 | } 34 | }).counter; 35 | 36 | System.out.println("There are " + count + " values that are non-negative."); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /hppc-template-processor/src/main/java/com/carrotsearch/hppc/generator/intrinsics/NewArray.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc.generator.intrinsics; 2 | 3 | import java.util.ArrayList; 4 | import java.util.regex.Matcher; 5 | 6 | import com.carrotsearch.hppc.generator.TemplateOptions; 7 | import com.carrotsearch.hppc.generator.Type; 8 | 9 | public class NewArray extends AbstractIntrinsicMethod { 10 | @Override 11 | public void invoke(Matcher m, StringBuilder sb, TemplateOptions templateOptions, String genericCast, ArrayList params) { 12 | expectArgumentCount(m, params, 1); 13 | 14 | genericCast = inferTemplateCastName(m, templateOptions, genericCast); 15 | Type type = inferTemplateType(m, templateOptions, genericCast); 16 | 17 | switch (type) { 18 | case GENERIC: 19 | sb.append(format("((%s[]) new Object [%s])", genericCast, params.get(0))); 20 | break; 21 | 22 | case BYTE: 23 | case CHAR: 24 | case DOUBLE: 25 | case FLOAT: 26 | case INT: 27 | case LONG: 28 | case SHORT: 29 | sb.append(format("(new %s [%s])", type.getType(), params.get(0))); 30 | break; 31 | 32 | default: 33 | throw unreachable(); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /hppc-benchmarks/src/main/java/com/carrotsearch/hppc/benchmarks/B001_ModXor.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc.benchmarks; 2 | 3 | import org.openjdk.jmh.annotations.Benchmark; 4 | import org.openjdk.jmh.annotations.Fork; 5 | import org.openjdk.jmh.annotations.Measurement; 6 | import org.openjdk.jmh.annotations.Scope; 7 | import org.openjdk.jmh.annotations.State; 8 | import org.openjdk.jmh.annotations.Warmup; 9 | import org.openjdk.jmh.runner.Runner; 10 | import org.openjdk.jmh.runner.RunnerException; 11 | import org.openjdk.jmh.runner.options.Options; 12 | import org.openjdk.jmh.runner.options.OptionsBuilder; 13 | 14 | @Fork(1) 15 | @Warmup(iterations = 5) 16 | @Measurement(iterations = 5) 17 | @State(Scope.Thread) 18 | public class B001_ModXor { 19 | private int v; 20 | private int mask = 0x238751; 21 | 22 | @Benchmark 23 | public int modOp() { 24 | v = v % mask++; 25 | return v; 26 | } 27 | 28 | @Benchmark 29 | public int xorOp() { 30 | v = v ^ mask++; 31 | return v; 32 | } 33 | 34 | public static void main(String[] args) throws RunnerException { 35 | Options opt = new OptionsBuilder() 36 | .include(B001_ModXor.class.getSimpleName()) 37 | .build(); 38 | 39 | new Runner(opt).run(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /hppc-template-processor/src/main/java/com/carrotsearch/hppc/generator/intrinsics/IsEmpty.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc.generator.intrinsics; 2 | 3 | import java.util.ArrayList; 4 | import java.util.regex.Matcher; 5 | 6 | import com.carrotsearch.hppc.generator.TemplateOptions; 7 | 8 | public class IsEmpty extends AbstractIntrinsicMethod { 9 | @Override 10 | public void invoke(Matcher m, StringBuilder sb, TemplateOptions templateOptions, String genericCast, ArrayList params) { 11 | expectArgumentCount(m, params, 1); 12 | 13 | switch (inferTemplateType(m, templateOptions, genericCast)) { 14 | case GENERIC: 15 | sb.append(format("((%s) == null)", params.get(0))); 16 | break; 17 | 18 | case FLOAT: 19 | sb.append(format("(Float.floatToIntBits(%s) == 0)", params.get(0))); 20 | break; 21 | 22 | case DOUBLE: 23 | sb.append(format("(Double.doubleToLongBits(%s) == 0)", params.get(0))); 24 | break; 25 | 26 | case BYTE: 27 | case CHAR: 28 | case INT: 29 | case LONG: 30 | case SHORT: 31 | sb.append(format("((%s) == 0)", params.get(0))); 32 | break; 33 | 34 | default: 35 | throw unreachable(); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /hppc/src/test/java/com/carrotsearch/hppc/EntryShiftingOnRemovalTest.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc; 2 | 3 | import java.util.HashSet; 4 | import java.util.Set; 5 | 6 | import org.junit.Test; 7 | 8 | import com.carrotsearch.randomizedtesting.RandomizedTest; 9 | import com.carrotsearch.randomizedtesting.annotations.Repeat; 10 | 11 | public class EntryShiftingOnRemovalTest extends RandomizedTest { 12 | @Test 13 | @Repeat(iterations = 10) 14 | public void testRemoveSanity() { 15 | @SuppressWarnings("deprecation") 16 | IntHashSet v = new IntHashSet(8, 0.5d, HashOrderMixing.none()) { 17 | @Override 18 | protected int hashKey(int key) { 19 | return key & 0xff; 20 | } 21 | }; 22 | 23 | Set ref = new HashSet(); 24 | for (int i = 0; i < 4; i++) { 25 | int r = randomInt() & 0xffff; 26 | ref.add(r); 27 | v.add(r); 28 | } 29 | 30 | Integer[] array = ref.toArray(new Integer[ref.size()]); 31 | int remove = randomFrom(array); 32 | ref.remove(remove); 33 | v.remove(remove); 34 | 35 | int[] actual = v.toArray(); 36 | assertTrue(actual.length == ref.size()); 37 | for (Integer ri : ref) { 38 | assertTrue(v.contains(ri)); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /etc/eclipse/hppc.test-templates.launch: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /hppc/src/main/templates/com/carrotsearch/hppc/KTypeBufferVisualizer.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc; 2 | 3 | /** 4 | * Reused buffer visualization routines. 5 | * 6 | * @see KTypeSet#visualizeKeyDistribution(int) 7 | * @see KTypeVTypeMap#visualizeKeyDistribution(int) 8 | */ 9 | class KTypeBufferVisualizer { 10 | static String visualizeKeyDistribution( 11 | /*! #if ($TemplateOptions.KTypeGeneric) !*/ Object [] /*! #else KType [] #end !*/ buffer, 12 | int max, 13 | int characters) { 14 | final StringBuilder b = new StringBuilder(); 15 | final char [] chars = ".123456789X".toCharArray(); 16 | for (int i = 1, start = -1; i <= characters; i++) { 17 | int end = (int) ((long) i * max / characters); 18 | 19 | if (start + 1 <= end) { 20 | int taken = 0; 21 | int slots = 0; 22 | for (int slot = start + 1; slot <= end; slot++, slots++) { 23 | if (!Intrinsics. isEmpty(buffer[slot])) { 24 | taken++; 25 | } 26 | } 27 | b.append(chars[Math.min(chars.length - 1, taken * chars.length / slots)]); 28 | start = end; 29 | } 30 | } 31 | while (b.length() < characters) { 32 | b.append(' '); 33 | } 34 | return b.toString(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /hppc-template-processor/src/main/java/com/carrotsearch/hppc/generator/intrinsics/Empty.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc.generator.intrinsics; 2 | 3 | import java.util.ArrayList; 4 | import java.util.regex.Matcher; 5 | 6 | import com.carrotsearch.hppc.generator.TemplateOptions; 7 | 8 | public class Empty extends AbstractIntrinsicMethod { 9 | @Override 10 | public void invoke(Matcher m, StringBuilder sb, TemplateOptions templateOptions, String genericCast, ArrayList params) { 11 | expectArgumentCount(m, params, 0); 12 | 13 | switch (inferTemplateType(m, templateOptions, genericCast)) { 14 | case GENERIC: 15 | sb.append("null"); 16 | break; 17 | 18 | case FLOAT: 19 | sb.append("0f"); 20 | break; 21 | 22 | case DOUBLE: 23 | sb.append("0d"); 24 | break; 25 | 26 | case BYTE: 27 | sb.append("((byte) 0)"); 28 | break; 29 | 30 | case CHAR: 31 | sb.append("((char) 0)"); 32 | break; 33 | 34 | case SHORT: 35 | sb.append("((short) 0)"); 36 | break; 37 | 38 | case INT: 39 | sb.append("0"); 40 | break; 41 | 42 | case LONG: 43 | sb.append("0L"); 44 | break; 45 | 46 | default: 47 | throw unreachable(); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /hppc/src/test/java/com/carrotsearch/hppc/BoundedProportionalArraySizingStrategyTest.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | 5 | import org.junit.Test; 6 | 7 | /** 8 | * Test case for bounded proportional sizing strategy. 9 | */ 10 | public class BoundedProportionalArraySizingStrategyTest 11 | { 12 | private BoundedProportionalArraySizingStrategy resizer; 13 | 14 | @Test(expected = BufferAllocationException.class) 15 | public void testBeyondIntRange() 16 | { 17 | resizer = new BoundedProportionalArraySizingStrategy(); 18 | resizer.grow( 19 | BoundedProportionalArraySizingStrategy.MAX_ARRAY_LENGTH, 20 | BoundedProportionalArraySizingStrategy.MAX_ARRAY_LENGTH, 1); 21 | } 22 | 23 | @Test 24 | public void testExactIntRange() 25 | { 26 | resizer = new BoundedProportionalArraySizingStrategy(); 27 | int size = BoundedProportionalArraySizingStrategy.MAX_ARRAY_LENGTH - 2; 28 | size = resizer.grow(size, size, 1); 29 | assertEquals(BoundedProportionalArraySizingStrategy.MAX_ARRAY_LENGTH, size); 30 | try { 31 | size = resizer.grow(size, size, 1); 32 | throw new RuntimeException("Unexpected."); 33 | } catch (BufferAllocationException e) { 34 | // Expected. 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /hppc/src/test/java/com/carrotsearch/hppc/IdentitySetsTest.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc; 2 | 3 | import static org.junit.Assert.*; 4 | 5 | import org.assertj.core.api.Assertions; 6 | import org.junit.Test; 7 | 8 | public class IdentitySetsTest 9 | { 10 | @Test 11 | public void testSanity() 12 | { 13 | ObjectIdentityHashSet m1 = new ObjectIdentityHashSet<>(); 14 | 15 | Integer a, b; 16 | Assertions.assertThat(m1.add(a = new Integer(1))).isTrue(); 17 | Assertions.assertThat(m1.add(a)).isFalse(); 18 | Assertions.assertThat(m1.add(b = new Integer(1))).isTrue(); 19 | Assertions.assertThat(m1.add(b)).isFalse(); 20 | 21 | Assertions.assertThat(m1.contains(a)).isTrue(); 22 | Assertions.assertThat(m1.contains(b)).isTrue(); 23 | Assertions.assertThat(m1.contains(new Integer(1))).isFalse(); 24 | 25 | Assertions.assertThat(m1.contains(null)).isFalse(); 26 | Assertions.assertThat(m1.add(null)).isTrue(); 27 | Assertions.assertThat(m1.add(null)).isFalse(); 28 | 29 | assertEquals(3, m1.size()); 30 | 31 | ObjectIdentityHashSet m2 = new ObjectIdentityHashSet<>(); 32 | m2.addAll(m1); 33 | 34 | Assertions.assertThat(m1).isEqualTo(m2); 35 | 36 | m2.remove(a); 37 | Assertions.assertThat(m1).isNotEqualTo(m2); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /hppc-benchmarks/src/main/java/com/carrotsearch/hppc/benchmarks/implementations/KolobokeIntSetOps.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc.benchmarks.implementations; 2 | 3 | import net.openhft.koloboke.collect.hash.HashConfig; 4 | import net.openhft.koloboke.collect.set.hash.HashIntSet; 5 | import net.openhft.koloboke.collect.set.hash.HashIntSets; 6 | 7 | import com.carrotsearch.hppc.benchmarks.IntSetOps; 8 | 9 | public class KolobokeIntSetOps implements IntSetOps { 10 | private final HashIntSet delegate; 11 | 12 | public KolobokeIntSetOps(int expectedElements, double loadFactor) { 13 | this.delegate = HashIntSets.getDefaultFactory() 14 | .withHashConfig(HashConfig.fromLoads(loadFactor / 2, loadFactor, loadFactor)).newMutableSet(); 15 | this.delegate.ensureCapacity(expectedElements); 16 | } 17 | 18 | @Override 19 | public void add(int key) { 20 | delegate.add(key); 21 | } 22 | 23 | @Override 24 | public void bulkAdd(int[] keys) { 25 | for (int key : keys) { 26 | delegate.add(key); 27 | } 28 | } 29 | 30 | @Override 31 | public int bulkContains(int[] keys) { 32 | int v = 0; 33 | for (int key : keys) { 34 | if (delegate.contains(key)) { 35 | v++; 36 | } 37 | } 38 | return v; 39 | } 40 | 41 | @Override 42 | public int[] iterationOrderArray() { 43 | return delegate.toIntArray(); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /hppc-benchmarks/src/main/java/com/carrotsearch/hppc/benchmarks/Library.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc.benchmarks; 2 | 3 | import com.carrotsearch.hppc.benchmarks.implementations.FastutilIntSetOps; 4 | import com.carrotsearch.hppc.benchmarks.implementations.HppcIntSetOps; 5 | import com.carrotsearch.hppc.benchmarks.implementations.HppcIntScatterSetOps; 6 | import com.carrotsearch.hppc.benchmarks.implementations.KolobokeIntSetOps; 7 | 8 | /** 9 | * Benchmarked libraries. 10 | */ 11 | public enum Library { 12 | HPPC { 13 | @Override 14 | public IntSetOps newIntSet(int expectedElements, double loadFactor) { 15 | return new HppcIntSetOps(expectedElements, loadFactor); 16 | } 17 | }, 18 | 19 | HPPC_SCATTER { 20 | @Override 21 | public IntSetOps newIntSet(int expectedElements, double loadFactor) { 22 | return new HppcIntScatterSetOps(expectedElements, loadFactor); 23 | } 24 | }, 25 | 26 | FASTUTIL { 27 | @Override 28 | public IntSetOps newIntSet(int expectedElements, double loadFactor) { 29 | return new FastutilIntSetOps(expectedElements, loadFactor); 30 | } 31 | }, 32 | 33 | KOLOBOKE { 34 | @Override 35 | public IntSetOps newIntSet(int expectedElements, double loadFactor) { 36 | return new KolobokeIntSetOps(expectedElements, loadFactor); 37 | } 38 | }; 39 | 40 | public abstract IntSetOps newIntSet(int expectedElements, double loadFactor); 41 | } -------------------------------------------------------------------------------- /etc/eclipse/configs/hppc-benchmarks/_externalToolBuilders/hppc.benchmarks-jmh.launch: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /hppc/src/main/java/com/carrotsearch/hppc/XorShift128P.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc; 2 | 3 | import java.util.Random; 4 | 5 | /** 6 | * A fast pseudo-random number generator. For simplicity, we do not implement all of {@link Random} methods. 7 | * 8 | * @see "http://xorshift.di.unimi.it/" 9 | * @see "http://xorshift.di.unimi.it/xorshift128plus.c" 10 | */ 11 | public class XorShift128P { 12 | /* 13 | * 128 bits of state. 14 | */ 15 | private long state0, state1; 16 | 17 | public XorShift128P(long seed) { 18 | state0 = notZero(BitMixer.mix64(seed)); 19 | state1 = notZero(BitMixer.mix64(seed + 1)); 20 | } 21 | 22 | public XorShift128P() { 23 | this(Containers.randomSeed64()); 24 | } 25 | 26 | public long nextLong() { 27 | long s1 = state0; 28 | long s0 = state1; 29 | state0 = s0; 30 | s1 ^= s1 << 23; 31 | return (state1 = (s1 ^ s0 ^ (s1 >>> 17) ^ (s0 >>> 26))) + s0; 32 | } 33 | 34 | public int nextInt() { 35 | return (int) nextLong(); 36 | } 37 | 38 | private static long notZero(long value) { 39 | return value == 0 ? 0xdeadbeefbabeL : value; 40 | } 41 | 42 | public int nextInt(int bound) { 43 | if (bound <= 0) { 44 | throw new IllegalArgumentException(); 45 | } 46 | 47 | int r = (nextInt() >>> 1); 48 | int m = bound - 1; 49 | if ((bound & m) == 0) { 50 | r = (int)((bound * (long) r) >> 31); 51 | } else { 52 | for (int u = r; 53 | u - (r = u % bound) + m < 0; 54 | u = nextInt() >>> 1) { 55 | } 56 | } 57 | 58 | return r; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /hppc/src/test/java/com/carrotsearch/hppc/HashContainersTest.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc; 2 | 3 | import org.junit.Test; 4 | 5 | import com.carrotsearch.randomizedtesting.RandomizedTest; 6 | 7 | import static com.carrotsearch.hppc.HashContainers.*; 8 | 9 | public class HashContainersTest extends RandomizedTest { 10 | /* */ 11 | @Test 12 | public void testCapacityCalculations() { 13 | assertEquals(MIN_HASH_ARRAY_LENGTH, minBufferSize(0, 0.5f)); 14 | assertEquals(MIN_HASH_ARRAY_LENGTH, minBufferSize(1, 0.5f)); 15 | 16 | assertEquals(0x20, minBufferSize(0x10, 0.5f)); 17 | assertEquals(0x40, minBufferSize(0x10, 0.49f)); 18 | 19 | int maxCapacity = maxElements(HashContainers.MAX_LOAD_FACTOR); 20 | assertEquals(0x40000000, minBufferSize(maxCapacity, MAX_LOAD_FACTOR)); 21 | 22 | // This would fill the array fully, validating the invariant, but should 23 | // be possible without reallocating the buffer. 24 | minBufferSize(maxCapacity + 1, MAX_LOAD_FACTOR); 25 | assertEquals(maxCapacity + 1, expandAtCount(MAX_HASH_ARRAY_LENGTH, MAX_LOAD_FACTOR)); 26 | 27 | try { 28 | // This should be impossible because it'd create a negative-sized array. 29 | minBufferSize(maxCapacity + 2, MAX_LOAD_FACTOR); 30 | fail(); 31 | } catch (BufferAllocationException e) { 32 | // Expected. 33 | } 34 | } 35 | 36 | /* */ 37 | @Test 38 | public void testLoadFactorOne() { 39 | assertEquals(0x100, minBufferSize(0x80, 1d)); 40 | assertEquals(0x7f, expandAtCount(0x80, 1d)); 41 | assertEquals(0xff, expandAtCount(0x100, 1d)); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /hppc-template-processor/src/main/java/com/carrotsearch/hppc/generator/intrinsics/Cast.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc.generator.intrinsics; 2 | 3 | import java.util.ArrayList; 4 | import java.util.regex.Matcher; 5 | 6 | import com.carrotsearch.hppc.generator.TemplateOptions; 7 | 8 | public class Cast extends AbstractIntrinsicMethod { 9 | @Override 10 | public void invoke(Matcher m, StringBuilder sb, TemplateOptions templateOptions, String genericCast, ArrayList params) { 11 | expectArgumentCount(m, params, 1); 12 | 13 | String cast = inferTemplateCastName(m, templateOptions, genericCast); 14 | switch (genericCast) { 15 | case "KType[]": 16 | case "KType": 17 | if (!templateOptions.hasKType()) { 18 | throw new RuntimeException("KType is not available for casting in this template?: " + m.group()); 19 | } 20 | if (templateOptions.isKTypeGeneric()) { 21 | cast = "(" + genericCast + ")"; 22 | } else { 23 | cast = ""; // dropped 24 | } 25 | break; 26 | 27 | case "VType[]": 28 | case "VType": 29 | if (!templateOptions.hasVType()) { 30 | throw new RuntimeException("VType is not available for casting in this template?: " + m.group()); 31 | } 32 | if (templateOptions.isVTypeGeneric()) { 33 | cast = "(" + genericCast + ")"; 34 | } else { 35 | cast = ""; // dropped 36 | } 37 | break; 38 | 39 | default: 40 | throw unreachable(); 41 | } 42 | 43 | sb.append(cast + " " + params.get(0)); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /etc/eclipse/configs/hppc/_externalToolBuilders/hppc.templates-generate.launch: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /hppc/src/main/javadoc/resources/overview.css: -------------------------------------------------------------------------------- 1 | .header ul li, .footer ul li { 2 | list-style: disc; 3 | font-size: 1em; 4 | } 5 | 6 | table.nice a, 7 | table.nice a:link, 8 | table.nice a:visited { 9 | border: none; 10 | } 11 | 12 | img { 13 | border: 0; 14 | margin-top: .5em; 15 | } 16 | 17 | table.nice { 18 | margin: 1em auto; 19 | border-collapse: collapse; 20 | } 21 | 22 | caption { 23 | color: #9ba9b4; 24 | font-size: .94em; 25 | letter-spacing: .1em; 26 | margin: 1em 0 0 0; 27 | padding: 0; 28 | caption-side: top; 29 | text-align: center; 30 | } 31 | 32 | table.nice tr.odd td { 33 | background: #f0f0f5; 34 | } 35 | 36 | table.nice tr.odd .column1 { 37 | background: #f0f0f5; 38 | font-weight: bold; 39 | } 40 | 41 | table.nice tr .column1 { 42 | background: #f9fcfe; 43 | font-weight: bold; 44 | } 45 | 46 | table.nice td { 47 | color: #526678; 48 | border: 1px solid #cfe4f8; 49 | padding: .3em 1em; 50 | text-align: center; 51 | } 52 | 53 | table.nice th { 54 | border: 1px solid #cfe4f8; 55 | font-weight: normal; 56 | color: #526678; 57 | text-align: left; 58 | padding: .3em 1em; 59 | } 60 | 61 | table.nice thead th { 62 | background: #e8e8f0; 63 | text-align: center; 64 | font: bold 1.2em/ 2em Arial, Helvetica, sans-serif; 65 | color: #66a3d3 66 | } 67 | 68 | table.nice tfoot th { 69 | text-align: center; 70 | background: #f4f9fe; 71 | } 72 | 73 | table.nice tfoot th strong { 74 | font: bold 1.2em Arial, Helvetica, sans-serif; 75 | margin: .5em .5em .5em 0; 76 | color: #66a3d3; 77 | } 78 | 79 | table.nice tfoot th em { 80 | color: #f03b58; 81 | font-weight: bold; 82 | font-size: 1.1em; 83 | font-style: normal; 84 | } 85 | 86 | table.nice thead th.empty { 87 | border-top: none; 88 | border-left: none; 89 | background: white; 90 | } 91 | 92 | .red { 93 | color: red; 94 | } 95 | 96 | .nobr { 97 | white-space: nowrap; 98 | } -------------------------------------------------------------------------------- /hppc-template-processor/src/main/java/com/carrotsearch/hppc/generator/intrinsics/Equals.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc.generator.intrinsics; 2 | 3 | import java.util.ArrayList; 4 | import java.util.regex.Matcher; 5 | 6 | import com.carrotsearch.hppc.generator.TemplateOptions; 7 | import com.carrotsearch.hppc.generator.Type; 8 | 9 | public class Equals extends AbstractIntrinsicMethod { 10 | @Override 11 | public void invoke(Matcher m, StringBuilder sb, TemplateOptions templateOptions, String genericCast, ArrayList arguments) { 12 | 13 | if (arguments.size() != 2 && 14 | arguments.size() != 3) { 15 | throw new RuntimeException(format("Expected exactly 2 or 3 arguments but was %d: %s(%s)", 16 | arguments.size(), 17 | m.group(), 18 | arguments)); 19 | } 20 | 21 | String v1 = arguments.remove(arguments.size() - 1); 22 | String v2 = arguments.remove(arguments.size() - 1); 23 | 24 | Type type = super.inferTemplateType(m, templateOptions, genericCast); 25 | switch (type) { 26 | case GENERIC: 27 | String comparer = arguments.isEmpty() ? "java.util.Objects" : arguments.get(0); 28 | sb.append(format("%s.equals(%s, %s)", comparer, v1, v2)); 29 | break; 30 | 31 | case FLOAT: 32 | sb.append(format("(Float.floatToIntBits(%s) == Float.floatToIntBits(%s))", v1, v2)); 33 | break; 34 | 35 | case DOUBLE: 36 | sb.append(format("(Double.doubleToLongBits(%s) == Double.doubleToLongBits(%s))", v1, v2)); 37 | break; 38 | 39 | case BYTE: 40 | case SHORT: 41 | case CHAR: 42 | case INT: 43 | case LONG: 44 | sb.append(format("((%s) == (%s))", v1, v2)); 45 | break; 46 | 47 | default: 48 | throw unreachable(); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /etc/eclipse/hppc.process-templates.launch: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /hppc/src/main/java/com/carrotsearch/hppc/AbstractIterator.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc; 2 | 3 | import java.util.Iterator; 4 | import java.util.NoSuchElementException; 5 | 6 | /** 7 | * Simplifies the implementation of iterators a bit. Modeled loosely after 8 | * Google Guava's API. 9 | */ 10 | public abstract class AbstractIterator implements Iterator { 11 | private final static int NOT_CACHED = 0; 12 | private final static int CACHED = 1; 13 | private final static int AT_END = 2; 14 | 15 | /** Current iterator state. */ 16 | private int state = NOT_CACHED; 17 | 18 | /** 19 | * The next element to be returned from {@link #next()} if fetched. 20 | */ 21 | private E nextElement; 22 | 23 | /** 24 | * {@inheritDoc} 25 | */ 26 | @Override 27 | public boolean hasNext() { 28 | if (state == NOT_CACHED) { 29 | state = CACHED; 30 | nextElement = fetch(); 31 | } 32 | return state == CACHED; 33 | } 34 | 35 | /** 36 | * {@inheritDoc} 37 | */ 38 | @Override 39 | public E next() { 40 | if (!hasNext()) { 41 | throw new NoSuchElementException(); 42 | } 43 | 44 | state = NOT_CACHED; 45 | return nextElement; 46 | } 47 | 48 | /** 49 | * Default implementation throws {@link UnsupportedOperationException}. 50 | */ 51 | @Override 52 | public void remove() { 53 | throw new UnsupportedOperationException(); 54 | } 55 | 56 | /** 57 | * Fetch next element. The implementation must return {@link #done()} when all 58 | * elements have been fetched. 59 | * 60 | * @return Returns the next value for the iterator or chain-calls {@link #done()}. 61 | */ 62 | protected abstract E fetch(); 63 | 64 | /** 65 | * Call when done. 66 | * 67 | * @return Returns a unique sentinel value to indicate end-of-iteration. 68 | */ 69 | protected final E done() { 70 | state = AT_END; 71 | return null; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /hppc/src/main/templates/com/carrotsearch/hppc/KTypeVTypeScatterMap.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc; 2 | 3 | import static com.carrotsearch.hppc.Containers.*; 4 | import static com.carrotsearch.hppc.HashContainers.*; 5 | 6 | /** 7 | * Same as {@link KTypeVTypeHashMap} but does not implement per-instance 8 | * key mixing strategy and uses a simpler (faster) bit distribution function. 9 | * 10 | *

Note: read about 11 | * important differences 12 | * between hash and scatter sets.

13 | */ 14 | /*! ${TemplateOptions.generatedAnnotation} !*/ 15 | public class KTypeVTypeScatterMap extends KTypeVTypeHashMap 16 | { 17 | /** 18 | * New instance with sane defaults. 19 | */ 20 | public KTypeVTypeScatterMap() { 21 | this(DEFAULT_EXPECTED_ELEMENTS); 22 | } 23 | 24 | /** 25 | * New instance with sane defaults. 26 | */ 27 | public KTypeVTypeScatterMap(int expectedElements) { 28 | this(expectedElements, DEFAULT_LOAD_FACTOR); 29 | } 30 | 31 | /** 32 | * New instance with sane defaults. 33 | */ 34 | @SuppressWarnings("deprecation") 35 | public KTypeVTypeScatterMap(int expectedElements, double loadFactor) { 36 | super(expectedElements, loadFactor, HashOrderMixing.none()); 37 | } 38 | 39 | /*! #if ($templateonly) !*/ 40 | @Override 41 | public 42 | /*! #else protected #end !*/ 43 | int hashKey(KType key) { 44 | return BitMixer.mixPhi(key); 45 | } 46 | 47 | /** 48 | * Creates a hash map from two index-aligned arrays of key-value pairs. 49 | */ 50 | public static KTypeVTypeScatterMap from(KType[] keys, VType[] values) { 51 | if (keys.length != values.length) { 52 | throw new IllegalArgumentException("Arrays of keys and values must have an identical length."); 53 | } 54 | 55 | KTypeVTypeScatterMap map = new KTypeVTypeScatterMap<>(keys.length); 56 | for (int i = 0; i < keys.length; i++) { 57 | map.put(keys[i], values[i]); 58 | } 59 | 60 | return map; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /hppc/src/main/templates/com/carrotsearch/hppc/KTypeScatterSet.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc; 2 | 3 | import static com.carrotsearch.hppc.Containers.*; 4 | import static com.carrotsearch.hppc.HashContainers.*; 5 | 6 | /** 7 | * Same as {@link KTypeHashSet} but does not implement per-instance key mixing 8 | * strategy and uses a simpler (faster) bit distribution function. 9 | * 10 | *

11 | * Note: read about important differences between hash and 13 | * scatter sets. 14 | *

15 | * 16 | * @see KTypeHashSet 17 | * @see HPPC interfaces diagram 18 | */ 19 | /*! ${TemplateOptions.generatedAnnotation} !*/ 20 | public class KTypeScatterSet extends KTypeHashSet { 21 | /** 22 | * New instance with sane defaults. 23 | */ 24 | public KTypeScatterSet() { 25 | this(DEFAULT_EXPECTED_ELEMENTS, DEFAULT_LOAD_FACTOR); 26 | } 27 | 28 | /** 29 | * New instance with sane defaults. 30 | */ 31 | public KTypeScatterSet(int expectedElements) { 32 | this(expectedElements, DEFAULT_LOAD_FACTOR); 33 | } 34 | 35 | /** 36 | * New instance with sane defaults. 37 | */ 38 | @SuppressWarnings("deprecation") 39 | public KTypeScatterSet(int expectedElements, double loadFactor) { 40 | super(expectedElements, loadFactor, HashOrderMixing.none()); 41 | } 42 | 43 | /*! #if ($templateonly) !*/ 44 | @Override 45 | public 46 | /*! #else protected #end !*/ 47 | int hashKey(KType key) { 48 | return BitMixer.mixPhi(key); 49 | } 50 | 51 | /** 52 | * Create a set from a variable number of arguments or an array of 53 | * KType. The elements are copied from the argument to the 54 | * internal buffer. 55 | */ 56 | /* #if ($TemplateOptions.KTypeGeneric) */ 57 | @SafeVarargs 58 | /* #end */ 59 | public static KTypeScatterSet from(KType... elements) { 60 | final KTypeScatterSet set = new KTypeScatterSet(elements.length); 61 | set.addAll(elements); 62 | return set; 63 | } 64 | } -------------------------------------------------------------------------------- /hppc-examples/src/test/java/com/carrotsearch/hppc/examples/HppcExample_001_IteratingOverLists.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc.examples; 2 | 3 | import static com.carrotsearch.hppc.examples.Helpers.*; 4 | 5 | import org.junit.Test; 6 | 7 | import com.carrotsearch.hppc.IntArrayList; 8 | import com.carrotsearch.hppc.cursors.IntCursor; 9 | import com.carrotsearch.hppc.procedures.IntProcedure; 10 | 11 | /** 12 | * Examples of how to iterate over HPPC lists. 13 | */ 14 | public class HppcExample_001_IteratingOverLists { 15 | public final IntArrayList list = IntArrayList.from(1, 1, 2, 3, 5); 16 | 17 | /** 18 | * All lists implement {@link Iterable} interface that returns a "cursor" 19 | * object that moves over the container's elements. The cursor object remains 20 | * identical for the entire iteration (very little memory overhead). 21 | */ 22 | @Test 23 | public void cursor() { 24 | for (IntCursor c : list) { 25 | printfln("list[%d] = %d", c.index, c.value); 26 | } 27 | } 28 | 29 | /** 30 | * A simple loop over indices of a list. 31 | */ 32 | @Test 33 | public void simpleLoop() throws Exception { 34 | for (int i = 0, max = list.size(); i < max; i++) { 35 | printfln("list[%d] = %d", i, list.get(i)); 36 | } 37 | } 38 | 39 | /** 40 | * A for-each type loop with an anonymous class. Note the index 41 | * of the current element is not passed to the procedure. 42 | */ 43 | @Test 44 | public void forEachLoop() throws Exception { 45 | list.forEach(new IntProcedure() { 46 | int index; 47 | 48 | public void apply(int value) { 49 | printfln("list[%d] = %d", index++, value); 50 | } 51 | }); 52 | } 53 | 54 | /** 55 | * A direct buffer access. 56 | * 57 | * Also see {@link HppcExample_005_IteratingOverObjectBuffers} 58 | * for caveats concerning iterating over object buffers. 59 | */ 60 | @Test 61 | public void directBufferLoop() throws Exception { 62 | final int[] buffer = list.buffer; 63 | final int size = list.size(); 64 | for (int i = 0; i < size; i++) { 65 | printfln("list[%d] = %d", i, buffer[i]); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /hppc-examples/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 4.0.0 5 | 6 | 7 | com.carrotsearch 8 | hppc-parent 9 | 0.8.0-SNAPSHOT 10 | ../pom.xml 11 | 12 | 13 | 14 | hppc-examples 15 | jar 16 | 17 | HPPC Examples 18 | 19 | 20 | true 21 | true 22 | 23 | 24 | 25 | 26 | com.carrotsearch 27 | hppc 28 | ${project.version} 29 | 30 | 31 | 32 | junit 33 | junit 34 | test 35 | 36 | 37 | 38 | com.carrotsearch.randomizedtesting 39 | randomizedtesting-runner 40 | test 41 | 42 | 43 | 44 | org.assertj 45 | assertj-core 46 | jar 47 | test 48 | 49 | 50 | 51 | 52 | 53 | 54 | com.carrotsearch.randomizedtesting 55 | junit4-maven-plugin 56 | 57 | 58 | junit4-tests 59 | 60 | junit4 61 | 62 | 63 | 64 | **/*HppcExample_* 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /hppc-examples/src/test/java/com/carrotsearch/hppc/examples/HppcExample_002_IteratingOverDeques.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc.examples; 2 | 3 | import static com.carrotsearch.hppc.examples.Helpers.*; 4 | 5 | import java.util.Iterator; 6 | 7 | import org.junit.Before; 8 | import org.junit.Test; 9 | 10 | import com.carrotsearch.hppc.IntArrayDeque; 11 | import com.carrotsearch.hppc.cursors.IntCursor; 12 | import com.carrotsearch.hppc.procedures.IntProcedure; 13 | 14 | /** 15 | * Examples of how to iterate over HPPC deques. 16 | */ 17 | public class HppcExample_002_IteratingOverDeques { 18 | 19 | public IntArrayDeque deque; 20 | 21 | @Before 22 | public void setup() { 23 | deque = new IntArrayDeque(); 24 | deque.addLast(1, 1, 2, 3, 5); 25 | } 26 | 27 | /** 28 | * All deques implement {@link Iterable} interface that returns a "cursor" 29 | * object that moves over the container's elements. The cursor object remains 30 | * identical for the entire iteration (very little memory overhead). 31 | * 32 | * The cursor's index points at the underlying buffer's position of a 33 | * given element. 34 | */ 35 | @Test 36 | public void cursorFirstToLast() { 37 | for (IntCursor c : deque) { 38 | printfln("deque[%d] = %d", c.index, c.value); 39 | } 40 | } 41 | 42 | /** 43 | * Reverse order iterator (cursor). 44 | */ 45 | @Test 46 | public void cursorLastToFirst() { 47 | for (Iterator i = deque.descendingIterator(); i.hasNext();) { 48 | IntCursor c = i.next(); 49 | printfln("deque[%d] = %d", c.index, c.value); 50 | } 51 | } 52 | 53 | /** 54 | * A for-each type loop with an anonymous class. 55 | */ 56 | @Test 57 | public void forEachLoop() throws Exception { 58 | deque.forEach(new IntProcedure() { 59 | public void apply(int value) { 60 | printfln("deque[?] = %d", value); 61 | } 62 | }); 63 | } 64 | 65 | /** 66 | * A for-each type loop with an anonymous class. 67 | */ 68 | @Test 69 | public void forEachLoopReversed() throws Exception { 70 | deque.descendingForEach(new IntProcedure() { 71 | public void apply(int value) { 72 | printfln("deque[?] = %d", value); 73 | } 74 | }); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /hppc-benchmarks/src/main/java/com/carrotsearch/hppc/benchmarks/B004_HashSet_CollisionAvalanche.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc.benchmarks; 2 | 3 | import org.openjdk.jmh.annotations.Benchmark; 4 | import org.openjdk.jmh.annotations.BenchmarkMode; 5 | import org.openjdk.jmh.annotations.Fork; 6 | import org.openjdk.jmh.annotations.Level; 7 | import org.openjdk.jmh.annotations.Measurement; 8 | import org.openjdk.jmh.annotations.Mode; 9 | import org.openjdk.jmh.annotations.Param; 10 | import org.openjdk.jmh.annotations.Scope; 11 | import org.openjdk.jmh.annotations.Setup; 12 | import org.openjdk.jmh.annotations.State; 13 | import org.openjdk.jmh.annotations.Warmup; 14 | import org.openjdk.jmh.runner.Runner; 15 | import org.openjdk.jmh.runner.RunnerException; 16 | import org.openjdk.jmh.runner.options.Options; 17 | import org.openjdk.jmh.runner.options.OptionsBuilder; 18 | 19 | @Fork(1) 20 | @Warmup(iterations = 5) 21 | @Measurement(iterations = 5) 22 | @State(Scope.Benchmark) 23 | public class B004_HashSet_CollisionAvalanche { 24 | @Param("0.75") 25 | public double loadFactor; 26 | 27 | @Param 28 | public Library library; 29 | 30 | private IntSetOps source; 31 | private IntSetOps target; 32 | private int[] keys; 33 | 34 | @Setup(Level.Trial) 35 | public void prepare() { 36 | // make sure we have nearly full load (dense source) 37 | int keyCount = (int) Math.ceil((1 << 19) / loadFactor) - 5000; 38 | int [] keys = new int [keyCount]; 39 | for (int i = keyCount; i-- != 0;) { 40 | keys[i] = i; 41 | } 42 | 43 | source = library.newIntSet(0, loadFactor); 44 | source.bulkAdd(keys); 45 | 46 | this.keys = source.iterationOrderArray(); 47 | } 48 | 49 | @Setup(Level.Iteration) 50 | public void prepareDelegate() { 51 | target = library.newIntSet(0, loadFactor); 52 | } 53 | 54 | @Benchmark() 55 | @BenchmarkMode(Mode.SingleShotTime) 56 | public Object run() { 57 | target.bulkAdd(keys); 58 | return target; 59 | } 60 | 61 | public static void main(String[] args) throws RunnerException { 62 | Options opt = new OptionsBuilder().include(B004_HashSet_CollisionAvalanche.class.getSimpleName()).build(); 63 | new Runner(opt).run(); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /hppc-benchmarks/src/main/java/com/carrotsearch/hppc/benchmarks/B003_HashSet_Contains.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc.benchmarks; 2 | 3 | import org.openjdk.jmh.annotations.Benchmark; 4 | import org.openjdk.jmh.annotations.BenchmarkMode; 5 | import org.openjdk.jmh.annotations.Fork; 6 | import org.openjdk.jmh.annotations.Level; 7 | import org.openjdk.jmh.annotations.Measurement; 8 | import org.openjdk.jmh.annotations.Mode; 9 | import org.openjdk.jmh.annotations.Param; 10 | import org.openjdk.jmh.annotations.Scope; 11 | import org.openjdk.jmh.annotations.Setup; 12 | import org.openjdk.jmh.annotations.State; 13 | import org.openjdk.jmh.annotations.Warmup; 14 | import org.openjdk.jmh.runner.Runner; 15 | import org.openjdk.jmh.runner.RunnerException; 16 | import org.openjdk.jmh.runner.options.Options; 17 | import org.openjdk.jmh.runner.options.OptionsBuilder; 18 | 19 | import com.carrotsearch.hppc.XorShift128P; 20 | 21 | @Fork(1) 22 | @Warmup(iterations = 5) 23 | @Measurement(iterations = 5) 24 | @State(Scope.Benchmark) 25 | public class B003_HashSet_Contains { 26 | @Param("0.75") 27 | public double loadFactor; 28 | 29 | @Param 30 | public Library library; 31 | 32 | @Param({"200"}) 33 | public int mbOfKeys; 34 | 35 | public int [] keys; 36 | public IntSetOps ops; 37 | 38 | @Setup(Level.Trial) 39 | public void prepare() { 40 | int keyCount = mbOfKeys * (1024 * 1024) / 4; 41 | keys = new int [keyCount]; 42 | 43 | XorShift128P rnd = new XorShift128P(0xdeadbeefL); 44 | for (int i = 0; i < keys.length; i++) { 45 | keys[i] = rnd.nextInt(2 * keys.length); 46 | } 47 | 48 | ops = library.newIntSet(keys.length, loadFactor); 49 | 50 | int[] existing = new int [keyCount]; 51 | for (int i = 0; i < keys.length; i++) { 52 | existing[i] = rnd.nextInt(2 * keys.length); 53 | } 54 | ops.bulkAdd(existing); 55 | } 56 | 57 | @Benchmark() 58 | @BenchmarkMode(Mode.SingleShotTime) 59 | public Object bulk() { 60 | return ops.bulkContains(keys); 61 | } 62 | 63 | public static void main(String[] args) throws RunnerException { 64 | Options opt = new OptionsBuilder().include(B003_HashSet_Contains.class.getSimpleName()).build(); 65 | new Runner(opt).run(); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /hppc-benchmarks/src/main/java/com/carrotsearch/hppc/benchmarks/B002_HashSet_Add.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc.benchmarks; 2 | 3 | import org.openjdk.jmh.annotations.Benchmark; 4 | import org.openjdk.jmh.annotations.BenchmarkMode; 5 | import org.openjdk.jmh.annotations.Fork; 6 | import org.openjdk.jmh.annotations.Level; 7 | import org.openjdk.jmh.annotations.Measurement; 8 | import org.openjdk.jmh.annotations.Mode; 9 | import org.openjdk.jmh.annotations.Param; 10 | import org.openjdk.jmh.annotations.Scope; 11 | import org.openjdk.jmh.annotations.Setup; 12 | import org.openjdk.jmh.annotations.State; 13 | import org.openjdk.jmh.annotations.Warmup; 14 | import org.openjdk.jmh.runner.Runner; 15 | import org.openjdk.jmh.runner.RunnerException; 16 | import org.openjdk.jmh.runner.options.Options; 17 | import org.openjdk.jmh.runner.options.OptionsBuilder; 18 | 19 | import com.carrotsearch.hppc.XorShift128P; 20 | 21 | @Fork(1) 22 | @Warmup(iterations = 5) 23 | @Measurement(iterations = 5) 24 | @State(Scope.Benchmark) 25 | public class B002_HashSet_Add { 26 | public static interface Ops { 27 | Object addAll(int [] keys); 28 | } 29 | 30 | @Param("0.75") 31 | public double loadFactor; 32 | 33 | @Param 34 | public Library library; 35 | 36 | @Param({"200"}) 37 | public int mbOfKeys; 38 | 39 | public int [] keys; 40 | public IntSetOps ops; 41 | 42 | @Setup(Level.Iteration) 43 | public void prepareDelegate() { 44 | ops = library.newIntSet(keys.length, loadFactor); 45 | } 46 | 47 | @Setup(Level.Trial) 48 | public void prepare() { 49 | int keyCount = mbOfKeys * (1024 * 1024) / 4; 50 | keys = new int [keyCount]; 51 | 52 | XorShift128P rnd = new XorShift128P(0xdeadbeefL); 53 | for (int i = 0; i < keys.length; i++) { 54 | keys[i] = rnd.nextInt(); 55 | } 56 | } 57 | 58 | @Benchmark() 59 | @BenchmarkMode(Mode.SingleShotTime) 60 | public Object bulk() { 61 | ops.bulkAdd(keys); 62 | return ops; 63 | } 64 | 65 | public static void main(String[] args) throws RunnerException { 66 | Options opt = new OptionsBuilder() 67 | .param("library", "HPPC_SCATTER") 68 | .include(B002_HashSet_Add.class.getSimpleName()) 69 | .build(); 70 | new Runner(opt).run(); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /hppc/src/test/java/com/carrotsearch/hppc/AbstractIteratorTest.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.Iterator; 6 | import java.util.List; 7 | import java.util.NoSuchElementException; 8 | 9 | import org.junit.Test; 10 | 11 | import static org.junit.Assert.*; 12 | 13 | /** 14 | * 15 | */ 16 | public class AbstractIteratorTest 17 | { 18 | public static class RangeIterator extends AbstractIterator 19 | { 20 | int start; 21 | int count; 22 | 23 | public RangeIterator(int start, int count) 24 | { 25 | this.start = start; 26 | this.count = count; 27 | } 28 | 29 | @Override 30 | protected Integer fetch() 31 | { 32 | if (count == 0) 33 | { 34 | return done(); 35 | } 36 | 37 | count--; 38 | return start++; 39 | } 40 | } 41 | 42 | @Test 43 | public void testEmpty() 44 | { 45 | RangeIterator i = new RangeIterator(1, 0); 46 | assertFalse(i.hasNext()); 47 | assertFalse(i.hasNext()); 48 | } 49 | 50 | @Test(expected = NoSuchElementException.class) 51 | public void testEmptyExceptionOnNext() 52 | { 53 | RangeIterator i = new RangeIterator(1, 0); 54 | i.next(); 55 | } 56 | 57 | @Test 58 | public void testNonEmpty() 59 | { 60 | RangeIterator i = new RangeIterator(1, 1); 61 | assertTrue(i.hasNext()); 62 | assertTrue(i.hasNext()); 63 | i.next(); 64 | assertFalse(i.hasNext()); 65 | assertFalse(i.hasNext()); 66 | try 67 | { 68 | i.next(); 69 | fail(); 70 | } 71 | catch (NoSuchElementException e) 72 | { 73 | // expected. 74 | } 75 | } 76 | 77 | @Test 78 | public void testValuesAllRight() 79 | { 80 | assertEquals(Arrays.asList(1), addAll(new RangeIterator(1, 1))); 81 | assertEquals(Arrays.asList(1, 2), addAll(new RangeIterator(1, 2))); 82 | assertEquals(Arrays.asList(1, 2, 3), addAll(new RangeIterator(1, 3))); 83 | } 84 | 85 | private static List addAll(Iterator i) 86 | { 87 | List t = new ArrayList(); 88 | while (i.hasNext()) 89 | t.add(i.next()); 90 | return t; 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /hppc/src/main/templates/com/carrotsearch/hppc/KTypeCollection.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc; 2 | 3 | import com.carrotsearch.hppc.predicates.KTypePredicate; 4 | 5 | /** 6 | * A collection allows basic, efficient operations on sets of elements 7 | * (difference and intersection). 8 | */ 9 | /*! ${TemplateOptions.generatedAnnotation} !*/ 10 | public interface KTypeCollection extends KTypeContainer { 11 | /** 12 | * Removes all occurrences of e from this collection. 13 | * 14 | * @param e 15 | * Element to be removed from this collection, if present. 16 | * @return The number of removed elements as a result of this call. 17 | */ 18 | public int removeAll(KType e); 19 | 20 | /** 21 | * Removes all elements in this collection that are present in c. 22 | * 23 | * @return Returns the number of removed elements. 24 | */ 25 | public int removeAll(KTypeLookupContainer c); 26 | 27 | /** 28 | * Removes all elements in this collection for which the given predicate 29 | * returns true. 30 | * 31 | * @return Returns the number of removed elements. 32 | */ 33 | public int removeAll(KTypePredicate predicate); 34 | 35 | /** 36 | * Keeps all elements in this collection that are present in c. 37 | * Runs in time proportional to the number of elements in this collection. 38 | * Equivalent of sets intersection. 39 | * 40 | * @return Returns the number of removed elements. 41 | */ 42 | public int retainAll(KTypeLookupContainer c); 43 | 44 | /** 45 | * Keeps all elements in this collection for which the given predicate returns 46 | * true. 47 | * 48 | * @return Returns the number of removed elements. 49 | */ 50 | public int retainAll(KTypePredicate predicate); 51 | 52 | /** 53 | * Removes all elements from this collection. 54 | * 55 | * @see #release() 56 | */ 57 | public void clear(); 58 | 59 | /** 60 | * Removes all elements from the collection and additionally releases any 61 | * internal buffers. Typically, if the object is to be reused, a simple 62 | * {@link #clear()} should be a better alternative since it'll avoid 63 | * reallocation. 64 | * 65 | * @see #clear() 66 | */ 67 | public void release(); 68 | } 69 | -------------------------------------------------------------------------------- /hppc-examples/src/test/java/com/carrotsearch/hppc/examples/HppcExample_003_IteratingOverSets.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc.examples; 2 | 3 | import static com.carrotsearch.hppc.examples.Helpers.*; 4 | import static org.assertj.core.api.Assertions.*; 5 | 6 | import org.junit.Before; 7 | import org.junit.Test; 8 | 9 | import com.carrotsearch.hppc.IntHashSet; 10 | import com.carrotsearch.hppc.IntScatterSet; 11 | import com.carrotsearch.hppc.cursors.IntCursor; 12 | import com.carrotsearch.hppc.procedures.IntProcedure; 13 | 14 | /** 15 | * Examples of how to iterate over HPPC sets. 16 | */ 17 | public class HppcExample_003_IteratingOverSets { 18 | 19 | public IntHashSet hashSet; 20 | public IntScatterSet scatterSet; 21 | 22 | @Before 23 | public void setup() { 24 | // Note that copying the other way around wouldn't be safe (and is thus impossible 25 | // because there is no IntScatterSet constructor that can copy keys from another 26 | // container). 27 | scatterSet = IntScatterSet.from(1, 1, 2, 3, 5, 0); 28 | hashSet = new IntHashSet(scatterSet); 29 | } 30 | 31 | /** 32 | * All sets implement the {@link Iterable} interface that returns a "cursor" 33 | * object that moves over the container's elements. The cursor object remains 34 | * identical for the entire iteration (very little memory overhead). 35 | * 36 | * The cursor's index points at the underlying buffer's position of a 37 | * given element, the cursor's value is the element itself. 38 | */ 39 | @Test 40 | public void cursor() { 41 | for (IntCursor c : scatterSet) { 42 | printfln("scatterSet contains %d (at buffer index %d)", c.value, c.index); 43 | assertThat(c.value).isEqualTo(scatterSet.keys[c.index]); 44 | } 45 | 46 | for (IntCursor c : hashSet) { 47 | printfln("hashSet contains %d (at buffer index %d)", c.value, c.index); 48 | assertThat(c.value).isEqualTo(hashSet.keys[c.index]); 49 | } 50 | } 51 | 52 | /** 53 | * A for-each type loop with an anonymous class. 54 | */ 55 | @Test 56 | public void forEachLoop() { 57 | scatterSet.forEach(new IntProcedure() { 58 | @Override 59 | public void apply(int value) { 60 | printfln("scatterSet contains %d", value); 61 | } 62 | }); 63 | 64 | hashSet.forEach(new IntProcedure() { 65 | @Override 66 | public void apply(int value) { 67 | printfln("hashSet contains %d", value); 68 | } 69 | }); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /hppc/src/test/java/com/carrotsearch/hppc/IdentityMapsTest.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc; 2 | 3 | import static org.junit.Assert.*; 4 | 5 | import org.junit.Test; 6 | 7 | public class IdentityMapsTest 8 | { 9 | @Test 10 | public void testSanity() 11 | { 12 | ObjectCharIdentityHashMap m1 = new ObjectCharIdentityHashMap<>(); 13 | 14 | Integer a, b; 15 | m1.put(a = new Integer(1), 'a'); 16 | m1.put(b = new Integer(1), 'b'); 17 | 18 | assertEquals('a', m1.get(a)); 19 | assertEquals('b', m1.get(b)); 20 | assertEquals(2, m1.size()); 21 | 22 | ObjectCharIdentityHashMap m2 = new ObjectCharIdentityHashMap<>(); 23 | m2.put(b, 'b'); 24 | m2.put(a, 'a'); 25 | 26 | assertEquals(m1, m2); 27 | assertEquals(m2, m1); 28 | 29 | m2.remove(a); 30 | m2.put(new Integer(1), 'a'); 31 | assertNotEquals(m1, m2); 32 | assertNotEquals(m2, m1); 33 | } 34 | 35 | @Test 36 | public void testEqualsComparesValuesByReference() 37 | { 38 | ObjectObjectIdentityHashMap m1 = new ObjectObjectIdentityHashMap<>(); 39 | ObjectObjectIdentityHashMap m2 = new ObjectObjectIdentityHashMap<>(); 40 | 41 | String a = "a"; 42 | String av = "av"; 43 | String b = "b"; 44 | String bv = "bv"; 45 | 46 | m1.put(a, av); 47 | m1.put(b, bv); 48 | 49 | m2.put(b, bv); 50 | m2.put(a, av); 51 | 52 | assertEquals(m1, m2); 53 | assertEquals(m2, m1); 54 | 55 | m2.put(a, new String(av)); 56 | assertNotEquals(m1, m2); 57 | assertNotEquals(m2, m1); 58 | } 59 | 60 | @Test 61 | public void testNaNsInValues() 62 | { 63 | ObjectDoubleIdentityHashMap m1 = new ObjectDoubleIdentityHashMap<>(); 64 | ObjectDoubleIdentityHashMap m2 = new ObjectDoubleIdentityHashMap<>(); 65 | 66 | String a = "a"; 67 | Double av = Double.NaN; 68 | 69 | m1.put(a, av); 70 | m2.put(a, av); 71 | 72 | assertEquals(m1, m2); 73 | assertEquals(m2, m1); 74 | 75 | // value storage is an array of primitives, so NaNs should be equal, even though the object 76 | // was different. 77 | m2.put(a, new Double(Double.NaN)); 78 | assertEquals(m1, m2); 79 | assertEquals(m2, m1); 80 | 81 | DoubleContainer values = m1.values(); 82 | assertTrue(values.contains(Double.NaN)); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /hppc/src/main/templates/com/carrotsearch/hppc/KTypeIndexedContainer.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc; 2 | 3 | import java.util.RandomAccess; 4 | 5 | /** 6 | * An indexed container provides random access to elements based on an 7 | * index. Indexes are zero-based. 8 | */ 9 | /*! ${TemplateOptions.generatedAnnotation} !*/ 10 | public interface KTypeIndexedContainer extends KTypeCollection, RandomAccess { 11 | /** 12 | * Removes the first element that equals e1, returning its 13 | * deleted position or -1 if the element was not found. 14 | */ 15 | public int removeFirst(KType e1); 16 | 17 | /** 18 | * Removes the last element that equals e1, returning its deleted 19 | * position or -1 if the element was not found. 20 | */ 21 | public int removeLast(KType e1); 22 | 23 | /** 24 | * Returns the index of the first occurrence of the specified element in this 25 | * list, or -1 if this list does not contain the element. 26 | */ 27 | public int indexOf(KType e1); 28 | 29 | /** 30 | * Returns the index of the last occurrence of the specified element in this 31 | * list, or -1 if this list does not contain the element. 32 | */ 33 | public int lastIndexOf(KType e1); 34 | 35 | /** 36 | * Adds an element to the end of this container (the last index is incremented 37 | * by one). 38 | */ 39 | public void add(KType e1); 40 | 41 | /** 42 | * Inserts the specified element at the specified position in this list. 43 | * 44 | * @param index 45 | * The index at which the element should be inserted, shifting any 46 | * existing and subsequent elements to the right. 47 | */ 48 | public void insert(int index, KType e1); 49 | 50 | /** 51 | * Replaces the element at the specified position in this list with the 52 | * specified element. 53 | * 54 | * @return Returns the previous value in the list. 55 | */ 56 | public KType set(int index, KType e1); 57 | 58 | /** 59 | * @return Returns the element at index index from the list. 60 | */ 61 | public KType get(int index); 62 | 63 | /** 64 | * Removes the element at the specified position in this container and returns 65 | * it. 66 | * 67 | * @see #removeFirst 68 | * @see #removeLast 69 | * @see #removeAll 70 | */ 71 | public KType remove(int index); 72 | 73 | /** 74 | * Removes from this container all of the elements with indexes between 75 | * fromIndex, inclusive, and toIndex, exclusive. 76 | */ 77 | public void removeRange(int fromIndex, int toIndex); 78 | } 79 | -------------------------------------------------------------------------------- /hppc/src/main/templates/com/carrotsearch/hppc/KTypeDeque.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc; 2 | 3 | import java.util.Deque; 4 | import java.util.Iterator; 5 | 6 | import com.carrotsearch.hppc.cursors.KTypeCursor; 7 | import com.carrotsearch.hppc.predicates.KTypePredicate; 8 | import com.carrotsearch.hppc.procedures.KTypeProcedure; 9 | 10 | /** 11 | * A linear collection that supports element insertion and removal at both ends. 12 | * 13 | * @see Deque 14 | */ 15 | /*! ${TemplateOptions.generatedAnnotation} !*/ 16 | public interface KTypeDeque extends KTypeCollection { 17 | /** 18 | * Removes the first element that equals e. 19 | * 20 | * @return The deleted element's index or -1 if the element 21 | * was not found. 22 | */ 23 | public int removeFirst(KType e); 24 | 25 | /** 26 | * Removes the last element that equals e. 27 | * 28 | * @return The deleted element's index or -1 if the element 29 | * was not found. 30 | */ 31 | public int removeLast(KType e); 32 | 33 | /** 34 | * Inserts the specified element at the front of this deque. 35 | */ 36 | public void addFirst(KType e); 37 | 38 | /** 39 | * Inserts the specified element at the end of this deque. 40 | */ 41 | public void addLast(KType e); 42 | 43 | /** 44 | * Retrieves and removes the first element of this deque. 45 | * 46 | * @return the head (first) element of this deque. 47 | */ 48 | public KType removeFirst(); 49 | 50 | /** 51 | * Retrieves and removes the last element of this deque. 52 | * 53 | * @return the tail of this deque. 54 | */ 55 | public KType removeLast(); 56 | 57 | /** 58 | * Retrieves the first element of this deque but does not remove it. 59 | * 60 | * @return the head of this deque. 61 | */ 62 | public KType getFirst(); 63 | 64 | /** 65 | * Retrieves the last element of this deque but does not remove it. 66 | * 67 | * @return the head of this deque. 68 | */ 69 | public KType getLast(); 70 | 71 | /** 72 | * @return An iterator over elements in this deque in tail-to-head order. 73 | */ 74 | public Iterator> descendingIterator(); 75 | 76 | /** 77 | * Applies a procedure to all elements in tail-to-head order. 78 | */ 79 | public > T descendingForEach(T procedure); 80 | 81 | /** 82 | * Applies a predicate to container elements as long, as the 83 | * predicate returns true. The iteration is interrupted 84 | * otherwise. 85 | */ 86 | public > T descendingForEach(T predicate); 87 | } 88 | -------------------------------------------------------------------------------- /hppc-examples/src/test/java/com/carrotsearch/hppc/examples/HppcExample_004_IteratingOverMaps.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc.examples; 2 | 3 | import static com.carrotsearch.hppc.examples.Helpers.*; 4 | import static org.assertj.core.api.Assertions.*; 5 | 6 | import org.junit.Before; 7 | import org.junit.Test; 8 | 9 | import com.carrotsearch.hppc.IntLongHashMap; 10 | import com.carrotsearch.hppc.IntLongScatterMap; 11 | import com.carrotsearch.hppc.cursors.IntLongCursor; 12 | import com.carrotsearch.hppc.procedures.IntLongProcedure; 13 | 14 | /** 15 | * Examples of how to iterate over HPPC maps. 16 | */ 17 | public class HppcExample_004_IteratingOverMaps { 18 | 19 | public IntLongHashMap hashMap; 20 | public IntLongScatterMap scatterMap; 21 | 22 | @Before 23 | public void setup() { 24 | // Note that copying the other way around wouldn't be safe (and is thus impossible 25 | // because there is no IntLongHashMap constructor that can copy keys from another 26 | // container). 27 | scatterMap = IntLongScatterMap.from( 28 | new int [] {1, 1, 2, 3, 5, 0}, 29 | new long [] {1, 2, 3, 4, 5, 6}); 30 | 31 | hashMap = new IntLongHashMap(scatterMap); 32 | } 33 | 34 | /** 35 | * All maps implement the {@link Iterable} interface that returns a "cursor" 36 | * object that moves over the container's elements. The cursor object remains 37 | * identical for the entire iteration (very little memory overhead). 38 | * 39 | * The cursor's index points at the underlying buffer's position of a 40 | * given element, the cursor's key is the key itself and cursor's value is the 41 | * value associated with the key. 42 | */ 43 | @Test 44 | public void cursor() { 45 | for (IntLongCursor c : scatterMap) { 46 | printfln("scatterMap %d => %d (at buffer index %d)", c.key, c.value, c.index); 47 | assertThat(c.value).isEqualTo(scatterMap.values[c.index]); 48 | assertThat(c.key).isEqualTo(scatterMap.keys[c.index]); 49 | } 50 | 51 | for (IntLongCursor c : hashMap) { 52 | printfln("hashMap %d => %d (at buffer index %d)", c.key, c.value, c.index); 53 | assertThat(c.value).isEqualTo(hashMap.values[c.index]); 54 | assertThat(c.key).isEqualTo(hashMap.keys[c.index]); 55 | } 56 | } 57 | 58 | /** 59 | * A for-each type loop with an anonymous class. 60 | */ 61 | @Test 62 | public void forEachLoop() { 63 | scatterMap.forEach(new IntLongProcedure() { 64 | @Override 65 | public void apply(int key, long value) { 66 | printfln("scatterMap %d => %d", key, value); 67 | } 68 | }); 69 | 70 | hashMap.forEach(new IntLongProcedure() { 71 | @Override 72 | public void apply(int key, long value) { 73 | printfln("hashMap %d => %d", key, value); 74 | } 75 | }); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /hppc/src/main/java/com/carrotsearch/hppc/Containers.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc; 2 | 3 | import java.security.PrivilegedAction; 4 | import java.util.logging.Level; 5 | import java.util.logging.Logger; 6 | 7 | /** 8 | * Constants used as defaults in containers. 9 | * 10 | * @see HashContainers 11 | */ 12 | public final class Containers { 13 | /** 14 | * The default number of expected elements for containers. 15 | */ 16 | public final static int DEFAULT_EXPECTED_ELEMENTS = 4; 17 | 18 | /** 19 | * External initial seed value. We do not care about multiple assignments 20 | * so not volatile. 21 | * 22 | * @see #randomSeed64() 23 | */ 24 | private static String testsSeedProperty; 25 | 26 | /** 27 | * Unique marker for {@link #testsSeedProperty}. 28 | */ 29 | private final static String NOT_AVAILABLE = new String(); 30 | 31 | private Containers() {} 32 | 33 | /** 34 | * Provides a (possibly) random initial seed for randomized stuff. 35 | * 36 | * If tests.seed property is available and accessible, 37 | * the returned value will be derived from the value of that property 38 | * and will be constant to ensure reproducibility in presence of the 39 | * randomized testing package. 40 | * 41 | * @see "https://github.com/carrotsearch/randomizedtesting" 42 | */ 43 | @SuppressForbidden 44 | public static long randomSeed64() { 45 | if (testsSeedProperty == null) { 46 | try { 47 | testsSeedProperty = java.security.AccessController.doPrivileged(new PrivilegedAction() { 48 | @Override 49 | public String run() { 50 | return System.getProperty("tests.seed", NOT_AVAILABLE); 51 | } 52 | }); 53 | } catch (SecurityException e) { 54 | // If failed on security exception, don't panic. 55 | testsSeedProperty = NOT_AVAILABLE; 56 | Logger.getLogger(Containers.class.getName()) 57 | .log(Level.INFO, "Failed to read 'tests.seed' property for initial random seed.", e); 58 | } 59 | } 60 | 61 | long initialSeed; 62 | if (testsSeedProperty != NOT_AVAILABLE) { 63 | initialSeed = testsSeedProperty.hashCode(); 64 | } else { 65 | // Mix something that is changing over time (nanoTime) 66 | // ... with something that is thread-local and relatively unique 67 | // even for very short time-spans (new Object's address from a TLAB). 68 | initialSeed = System.nanoTime() ^ 69 | System.identityHashCode(new Object()); 70 | } 71 | return BitMixer.mix64(initialSeed); 72 | } 73 | 74 | /** 75 | * Reset state for tests. 76 | */ 77 | static void test$reset() { 78 | testsSeedProperty = null; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /hppc/src/main/java/com/carrotsearch/hppc/ObjectIdentityHashSet.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc; 2 | 3 | import static com.carrotsearch.hppc.HashContainers.*; 4 | import static com.carrotsearch.hppc.Containers.*; 5 | 6 | /** 7 | * A reference-equality (identity) hash set. 8 | */ 9 | public class ObjectIdentityHashSet extends ObjectHashSet { 10 | /** 11 | * New instance with sane defaults. 12 | */ 13 | public ObjectIdentityHashSet() { 14 | this(DEFAULT_EXPECTED_ELEMENTS, DEFAULT_LOAD_FACTOR); 15 | } 16 | 17 | /** 18 | * New instance with sane defaults. 19 | */ 20 | public ObjectIdentityHashSet(int expectedElements) { 21 | this(expectedElements, DEFAULT_LOAD_FACTOR); 22 | } 23 | 24 | /** 25 | * New instance with sane defaults. 26 | */ 27 | public ObjectIdentityHashSet(int expectedElements, double loadFactor) { 28 | this(expectedElements, loadFactor, HashOrderMixing.randomized()); 29 | } 30 | 31 | /** 32 | * New instance with the provided defaults. 33 | * 34 | * @param expectedElements 35 | * The expected number of elements guaranteed not to cause a rehash (inclusive). 36 | * @param loadFactor 37 | * The load factor for internal buffers. Insane load factors (zero, full capacity) 38 | * are rejected by {@link #verifyLoadFactor(double)}. 39 | * @param orderMixer 40 | * Hash key order mixing strategy. See {@link HashOrderMixing} for predefined 41 | * implementations. Use constant mixers only if you understand the potential 42 | * consequences. 43 | */ 44 | public ObjectIdentityHashSet(int expectedElements, double loadFactor, HashOrderMixingStrategy orderMixer) { 45 | this.orderMixer = orderMixer; 46 | this.loadFactor = verifyLoadFactor(loadFactor); 47 | ensureCapacity(expectedElements); 48 | } 49 | 50 | /** 51 | * New instance copying elements from another {@link ObjectContainer}. 52 | */ 53 | public ObjectIdentityHashSet(ObjectContainer container) { 54 | this(container.size()); 55 | addAll(container); 56 | } 57 | 58 | @Override 59 | protected int hashKey(KType key) { 60 | assert key != null; // Handled as a special case (empty slot marker). 61 | return BitMixer.mix(key, this.keyMixer); 62 | } 63 | 64 | @Override 65 | protected boolean equals(Object v1, Object v2) { 66 | return v1 == v2; 67 | } 68 | 69 | /** 70 | * Create a set from a variable number of arguments or an array of 71 | * KType. The elements are copied from the argument to the 72 | * internal buffer. 73 | */ 74 | @SafeVarargs 75 | public static ObjectIdentityHashSet from(KType... elements) { 76 | final ObjectIdentityHashSet set = new ObjectIdentityHashSet(elements.length); 77 | set.addAll(elements); 78 | return set; 79 | } 80 | } -------------------------------------------------------------------------------- /hppc-template-processor/src/main/java/com/carrotsearch/hppc/generator/TemplateOptions.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc.generator; 2 | 3 | import java.nio.file.Path; 4 | import java.text.SimpleDateFormat; 5 | import java.util.Date; 6 | import java.util.Locale; 7 | 8 | import com.google.common.base.Preconditions; 9 | 10 | /** 11 | * Template options for velocity directives in templates. 12 | */ 13 | public class TemplateOptions { 14 | public static final String TEMPLATE_FILE_TOKEN = "__TEMPLATE_SOURCE__"; 15 | 16 | private boolean ignore; 17 | 18 | public Type ktype; 19 | public Type vtype; 20 | 21 | public Path templateFile; 22 | 23 | public TemplateOptions(Type ktype) { 24 | this(ktype, null); 25 | } 26 | 27 | public TemplateOptions(Type ktype, Type vtype) { 28 | this.ktype = ktype; 29 | this.vtype = vtype; 30 | } 31 | 32 | public void setIgnored(boolean ignore) { 33 | this.ignore = ignore; 34 | } 35 | 36 | public boolean isIgnored() { 37 | return ignore; 38 | } 39 | 40 | public boolean isKTypePrimitive() { 41 | return ktype != Type.GENERIC; 42 | } 43 | 44 | public boolean isVTypePrimitive() { 45 | return getVType() != Type.GENERIC; 46 | } 47 | 48 | public boolean isKTypeGeneric() { 49 | return ktype == Type.GENERIC; 50 | } 51 | 52 | public boolean isVTypeGeneric() { 53 | return getVType() == Type.GENERIC; 54 | } 55 | 56 | public boolean isAllGeneric() { 57 | return isKTypeGeneric() && isVTypeGeneric(); 58 | } 59 | 60 | public boolean isAnyPrimitive() { 61 | return isKTypePrimitive() || isVTypePrimitive(); 62 | } 63 | 64 | public boolean isAnyGeneric() { 65 | return isKTypeGeneric() || (hasVType() && isVTypeGeneric()); 66 | } 67 | 68 | public boolean hasVType() { 69 | return vtype != null; 70 | } 71 | 72 | public boolean hasKType() { 73 | return true; 74 | } 75 | 76 | public Type getKType() { 77 | Preconditions.checkArgument(hasKType(), "Template does not specify KType."); 78 | return ktype; 79 | } 80 | 81 | public Type getVType() { 82 | Preconditions.checkArgument(hasVType(), "Template does not specify VType."); 83 | return vtype; 84 | } 85 | 86 | /* 87 | * Returns the current time in ISO format. 88 | */ 89 | public String getTimeNow() { 90 | SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.ROOT); 91 | return format.format(new Date()); 92 | } 93 | 94 | public String getTemplateFile() { 95 | return templateFile.getFileName().toString(); 96 | } 97 | 98 | public String getGeneratedAnnotation() { 99 | return String.format(Locale.ROOT, 100 | "@javax.annotation.Generated(\n" + 101 | " date = \"%s\",\n" + 102 | " value = \"%s\")", 103 | getTimeNow(), 104 | TEMPLATE_FILE_TOKEN); 105 | } 106 | } -------------------------------------------------------------------------------- /hppc-template-processor/src/main/java/com/carrotsearch/hppc/generator/intrinsics/AbstractIntrinsicMethod.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc.generator.intrinsics; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Locale; 5 | import java.util.regex.Matcher; 6 | 7 | import com.carrotsearch.hppc.generator.IntrinsicMethod; 8 | import com.carrotsearch.hppc.generator.TemplateOptions; 9 | import com.carrotsearch.hppc.generator.Type; 10 | 11 | abstract class AbstractIntrinsicMethod implements IntrinsicMethod { 12 | protected static Type inferTemplateType(Matcher m, TemplateOptions templateOptions, String templateCast) { 13 | templateCast = inferTemplateCastName(m, templateOptions, templateCast); 14 | 15 | Type type; 16 | switch (templateCast) { 17 | case "KType": 18 | if (!templateOptions.hasKType()) { 19 | throw new RuntimeException(format( 20 | "Template cast requires %s but the template does not have it: %s", 21 | templateCast, 22 | m.group())); 23 | } 24 | type = templateOptions.getKType(); 25 | break; 26 | case "VType": 27 | if (!templateOptions.hasVType()) { 28 | throw new RuntimeException(format( 29 | "Template cast requires %s but the template does not have it: %s", 30 | templateCast, 31 | m.group())); 32 | } 33 | type = templateOptions.getVType(); 34 | break; 35 | default: 36 | throw new RuntimeException(format( 37 | "Ukrecognized template cast to %s in: %s", 38 | templateCast, 39 | m.group())); 40 | } 41 | return type; 42 | } 43 | 44 | protected static String inferTemplateCastName(Matcher m, TemplateOptions templateOptions, String templateCast) { 45 | if (templateCast == null || templateCast.isEmpty()) { 46 | if (templateOptions.hasKType() && !templateOptions.hasVType()) { 47 | templateCast = "KType"; 48 | } else if (templateOptions.hasVType() && !templateOptions.hasKType()) { 49 | templateCast = "VType"; 50 | } 51 | } 52 | 53 | if (templateCast == null) { 54 | throw new RuntimeException(format( 55 | "Couldn't infer template type of: %s", 56 | m.group())); 57 | } 58 | return templateCast; 59 | } 60 | 61 | protected static void expectArgumentCount(Matcher m, ArrayList arguments, int expectedCount) { 62 | if (arguments.size() != expectedCount) { 63 | throw new RuntimeException(format("Expected exactly %d arguments but was %d: %s(%s)", 64 | expectedCount, 65 | arguments.size(), 66 | m.group(), 67 | arguments)); 68 | } 69 | } 70 | 71 | protected static String format(String format, Object... args) { 72 | return String.format(Locale.ROOT, format, args); 73 | } 74 | 75 | protected RuntimeException unreachable() { 76 | throw new RuntimeException("Unreachable block reached."); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /hppc/src/main/templates/com/carrotsearch/hppc/AbstractKTypeCollection.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc; 2 | 3 | import java.util.Arrays; 4 | 5 | import com.carrotsearch.hppc.cursors.KTypeCursor; 6 | import com.carrotsearch.hppc.predicates.KTypePredicate; 7 | 8 | /** 9 | * Common superclass for collections. 10 | */ 11 | /*! #if ($TemplateOptions.KTypeGeneric) !*/ 12 | @SuppressWarnings("unchecked") 13 | /*! #end !*/ 14 | /*! ${TemplateOptions.generatedAnnotation} !*/ 15 | abstract class AbstractKTypeCollection 16 | implements /*! #if ($templateonly) !*/ Intrinsics.EqualityFunction, /*! #end !*/ 17 | KTypeCollection 18 | { 19 | /** 20 | * Default implementation uses a predicate for removal. 21 | */ 22 | @Override 23 | public int removeAll(final KTypeLookupContainer c) { 24 | // We know c holds sub-types of KType and we're not modifying c, so go unchecked. 25 | return this.removeAll(new KTypePredicate() { 26 | public boolean apply(KType k) { 27 | return c.contains(k); 28 | } 29 | }); 30 | } 31 | 32 | /** 33 | * Default implementation uses a predicate for retaining. 34 | */ 35 | @Override 36 | public int retainAll(final KTypeLookupContainer c) { 37 | // We know c holds sub-types of KType and we're not modifying c, so go unchecked. 38 | return this.removeAll(new KTypePredicate() { 39 | public boolean apply(KType k) { 40 | return !c.contains(k); 41 | } 42 | }); 43 | } 44 | 45 | /** 46 | * Default implementation redirects to {@link #removeAll(KTypePredicate)} and 47 | * negates the predicate. 48 | */ 49 | @Override 50 | public int retainAll(final KTypePredicate predicate) { 51 | return removeAll(new KTypePredicate() { 52 | public boolean apply(KType value) { 53 | return !predicate.apply(value); 54 | }; 55 | }); 56 | } 57 | 58 | /** 59 | * Default implementation of copying to an array. 60 | */ 61 | @Override 62 | /*!#if ($TemplateOptions.KTypePrimitive) 63 | public KType [] toArray() 64 | #else !*/ 65 | public Object[] toArray() 66 | /*! #end !*/ 67 | { 68 | KType[] array = Intrinsics. newArray(size()); 69 | int i = 0; 70 | for (KTypeCursor c : this) { 71 | array[i++] = c.value; 72 | } 73 | return array; 74 | } 75 | 76 | /*!#if ($TemplateOptions.KTypeGeneric) !*/ 77 | public T [] toArray(Class componentClass) { 78 | final int size = size(); 79 | final T[] array = (T[]) java.lang.reflect.Array.newInstance(componentClass, size); 80 | int i = 0; 81 | for (KTypeCursor c : this) { 82 | array[i++] = (T) c.value; 83 | } 84 | return array; 85 | } 86 | /*! #end !*/ 87 | 88 | /** 89 | * Convert the contents of this container to a human-friendly string. 90 | */ 91 | @Override 92 | public String toString() { 93 | return Arrays.toString(this.toArray()); 94 | } 95 | 96 | /*! #if ($TemplateOptions.KTypeGeneric) !*/ 97 | /*! #if ($templateonly) !*/ 98 | @Override 99 | public 100 | /*! #else protected #end !*/ boolean equals(Object v1, Object v2) { 101 | return (v1 == v2) || (v1 != null && v1.equals(v2)); 102 | } 103 | /*! #end !*/ 104 | } 105 | -------------------------------------------------------------------------------- /hppc/src/main/java/com/carrotsearch/hppc/BitMixer.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc; 2 | 3 | /** 4 | * Bit mixing utilities. The purpose of these methods is to evenly distribute key space over int32 5 | * range. 6 | */ 7 | public final class BitMixer { 8 | 9 | // Don't bother mixing very small key domains much. 10 | public static int mix(byte key) { return key * PHI_C32; } 11 | public static int mix(byte key, int seed) { return (key ^ seed) * PHI_C32; } 12 | 13 | public static int mix(short key) { return mixPhi(key); } 14 | public static int mix(short key, int seed) { return mixPhi(key ^ seed); } 15 | 16 | public static int mix(char key) { return mixPhi(key); } 17 | public static int mix(char key, int seed) { return mixPhi(key ^ seed); } 18 | 19 | // Better mix for larger key domains. 20 | public static int mix(int key) { return mix32(key); } 21 | public static int mix(int key, int seed) { return mix32(key ^ seed); } 22 | 23 | public static int mix(float key) { return mix32(Float.floatToIntBits(key)); } 24 | public static int mix(float key, int seed) { return mix32(Float.floatToIntBits(key) ^ seed); } 25 | 26 | public static int mix(double key) { return (int) mix64(Double.doubleToLongBits(key)); } 27 | public static int mix(double key, int seed) { return (int) mix64(Double.doubleToLongBits(key) ^ seed); } 28 | 29 | public static int mix(long key) { return (int) mix64(key); } 30 | public static int mix(long key, int seed) { return (int) mix64(key ^ seed); } 31 | 32 | public static int mix(Object key) { return key == null ? 0 : mix32(key.hashCode()); } 33 | public static int mix(Object key, int seed) { return key == null ? 0 : mix32(key.hashCode() ^ seed); } 34 | 35 | /** 36 | * MH3's plain finalization step. 37 | */ 38 | public static int mix32(int k) { 39 | k = (k ^ (k >>> 16)) * 0x85ebca6b; 40 | k = (k ^ (k >>> 13)) * 0xc2b2ae35; 41 | return k ^ (k >>> 16); 42 | } 43 | 44 | /** 45 | * Computes David Stafford variant 9 of 64bit mix function (MH3 finalization step, 46 | * with different shifts and constants). 47 | * 48 | * Variant 9 is picked because it contains two 32-bit shifts which could be possibly 49 | * optimized into better machine code. 50 | * 51 | * @see "http://zimbry.blogspot.com/2011/09/better-bit-mixing-improving-on.html" 52 | */ 53 | public static long mix64(long z) { 54 | z = (z ^ (z >>> 32)) * 0x4cd6944c5cc20b6dL; 55 | z = (z ^ (z >>> 29)) * 0xfc12c5b19d3259e9L; 56 | return z ^ (z >>> 32); 57 | } 58 | 59 | /* 60 | * Golden ratio bit mixers. 61 | */ 62 | 63 | private static final int PHI_C32 = 0x9e3779b9; 64 | private static final long PHI_C64 = 0x9e3779b97f4a7c15L; 65 | 66 | public static int mixPhi(byte k) { final int h = k * PHI_C32; return h ^ (h >>> 16); } 67 | public static int mixPhi(char k) { final int h = k * PHI_C32; return h ^ (h >>> 16); } 68 | public static int mixPhi(short k) { final int h = k * PHI_C32; return h ^ (h >>> 16); } 69 | public static int mixPhi(int k) { final int h = k * PHI_C32; return h ^ (h >>> 16); } 70 | public static int mixPhi(float k) { final int h = Float.floatToIntBits(k) * PHI_C32; return h ^ (h >>> 16); } 71 | public static int mixPhi(double k) { final long h = Double.doubleToLongBits(k) * PHI_C64; return (int) (h ^ (h >>> 32)); } 72 | public static int mixPhi(long k) { final long h = k * PHI_C64; return (int) (h ^ (h >>> 32)); } 73 | public static int mixPhi(Object k) { final int h = (k == null ? 0 : k.hashCode() * PHI_C32); return h ^ (h >>> 16); } 74 | } 75 | -------------------------------------------------------------------------------- /hppc/src/test/templates/com/carrotsearch/hppc/AbstractKTypeTest.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc; 2 | 3 | import org.junit.Rule; 4 | import org.junit.rules.MethodRule; 5 | 6 | import com.carrotsearch.randomizedtesting.RandomizedTest; 7 | 8 | 9 | /** 10 | * Unit helpers for KType. 11 | */ 12 | /*! ${TemplateOptions.generatedAnnotation} !*/ 13 | /*! #if ($TemplateOptions.KTypeGeneric) !*/ 14 | @SuppressWarnings("unchecked") 15 | /*! #end !*/ 16 | public abstract class AbstractKTypeTest extends RandomizedTest 17 | { 18 | /** 19 | * Require assertions for all tests. 20 | */ 21 | @Rule 22 | public MethodRule requireAssertions = new RequireAssertionsRule(); 23 | 24 | /* Ready to use key values. */ 25 | 26 | protected KType keyE = Intrinsics. empty(); 27 | protected KType key0 = cast(0), k0 = key0; 28 | protected KType key1 = cast(1), k1 = key1; 29 | protected KType key2 = cast(2), k2 = key2; 30 | protected KType key3 = cast(3), k3 = key3; 31 | protected KType key4 = cast(4), k4 = key4; 32 | protected KType key5 = cast(5), k5 = key5; 33 | protected KType key6 = cast(6), k6 = key6; 34 | protected KType key7 = cast(7), k7 = key7; 35 | protected KType key8 = cast(8), k8 = key8; 36 | protected KType key9 = cast(9), k9 = key9; 37 | 38 | /** 39 | * Convert to target type from an integer used to test stuff. 40 | */ 41 | public KType cast(Integer v) 42 | { 43 | /*! #if ($TemplateOptions.KTypePrimitive) 44 | return (KType) v.intValue(); 45 | #else !*/ 46 | // @SuppressWarnings("unchecked") 47 | KType k = (KType)(Object) v; 48 | return k; 49 | /*! #end !*/ 50 | } 51 | 52 | public KType [] asArray(int... ints) 53 | { 54 | KType [] values = Intrinsics. newArray(ints.length); 55 | for (int i = 0; i < ints.length; i++) 56 | values[i] = (KType) /*! #if ($TemplateOptions.KTypeGeneric) !*/ (Object) /*! #end !*/ ints[i]; 57 | return values; 58 | } 59 | 60 | /** 61 | * Create a new array of a given type and copy the arguments to this array. 62 | */ 63 | /* #if ($TemplateOptions.KTypeGeneric) */ 64 | @SafeVarargs 65 | /* #end */ 66 | public final KType [] newArray(KType... elements) 67 | { 68 | return newArray0(elements); 69 | } 70 | 71 | /* #if ($TemplateOptions.KTypeGeneric) */ 72 | @SafeVarargs 73 | /* #end */ 74 | private final KType [] newArray0(KType... elements) 75 | { 76 | return elements; 77 | } 78 | 79 | public KType [] newArray(KType v0) { return this.newArray0(v0); } 80 | public KType [] newArray(KType v0, KType v1) { return this.newArray0(v0, v1); } 81 | public KType [] newArray(KType v0, KType v1, KType v2) { return this.newArray0(v0, v1, v2); } 82 | public KType [] newArray(KType v0, KType v1, KType v2, KType v3) { return this.newArray0(v0, v1, v2, v3); } 83 | public KType [] newArray(KType v0, KType v1, KType v2, KType v3, 84 | KType v4, KType v5, KType v6) { return this.newArray0(v0, v1, v2, v3, v4, v5, v6); } 85 | public KType [] newArray(KType v0, KType v1, KType v2, KType v3, 86 | KType v4, KType v5) { return this.newArray0(v0, v1, v2, v3, v4, v5); } 87 | public KType [] newArray(KType v0, KType v1, KType v2, KType v3, 88 | KType v4) { return this.newArray0(v0, v1, v2, v3, v4); } 89 | public KType [] newArray(KType v0, KType v1, KType v2, KType v3, 90 | KType v4, KType v5, KType v6, KType v7) { return this.newArray0(v0, v1, v2, v3, v4, v5, v6, v7); } 91 | } 92 | -------------------------------------------------------------------------------- /hppc/src/main/java/com/carrotsearch/hppc/HashContainers.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc; 2 | 3 | public final class HashContainers { 4 | /** 5 | * Maximum array size for hash containers (power-of-two and still 6 | * allocable in Java, not a negative int). 7 | */ 8 | public final static int MAX_HASH_ARRAY_LENGTH = 0x80000000 >>> 1; 9 | 10 | /** 11 | * Minimum hash buffer size. 12 | */ 13 | public final static int MIN_HASH_ARRAY_LENGTH = 4; 14 | 15 | /** 16 | * Default load factor. 17 | */ 18 | public final static float DEFAULT_LOAD_FACTOR = 0.75f; 19 | 20 | /** 21 | * Minimal sane load factor (99 empty slots per 100). 22 | */ 23 | public final static float MIN_LOAD_FACTOR = 1 / 100.0f; 24 | 25 | /** 26 | * Maximum sane load factor (1 empty slot per 100). 27 | */ 28 | public final static float MAX_LOAD_FACTOR = 99 / 100.0f; 29 | 30 | /** 31 | * Compute and return the maximum number of elements (inclusive) 32 | * that can be stored in a hash container for a given load factor. 33 | */ 34 | public static int maxElements(double loadFactor) { 35 | checkLoadFactor(loadFactor, 0, 1); 36 | return expandAtCount(MAX_HASH_ARRAY_LENGTH, loadFactor) - 1; 37 | } 38 | 39 | /** */ 40 | static int minBufferSize(int elements, double loadFactor) { 41 | if (elements < 0) { 42 | throw new IllegalArgumentException( 43 | "Number of elements must be >= 0: " + elements); 44 | } 45 | 46 | long length = (long) Math.ceil(elements / loadFactor); 47 | if (length == elements) { 48 | length++; 49 | } 50 | length = Math.max(MIN_HASH_ARRAY_LENGTH, BitUtil.nextHighestPowerOfTwo(length)); 51 | 52 | if (length > MAX_HASH_ARRAY_LENGTH) { 53 | throw new BufferAllocationException( 54 | "Maximum array size exceeded for this load factor (elements: %d, load factor: %f)", 55 | elements, 56 | loadFactor); 57 | } 58 | 59 | return (int) length; 60 | } 61 | 62 | /** */ 63 | static int nextBufferSize(int arraySize, int elements, double loadFactor) { 64 | assert checkPowerOfTwo(arraySize); 65 | if (arraySize == MAX_HASH_ARRAY_LENGTH) { 66 | throw new BufferAllocationException( 67 | "Maximum array size exceeded for this load factor (elements: %d, load factor: %f)", 68 | elements, 69 | loadFactor); 70 | } 71 | 72 | return (int) arraySize << 1; 73 | } 74 | 75 | /** */ 76 | static int expandAtCount(int arraySize, double loadFactor) { 77 | assert checkPowerOfTwo(arraySize); 78 | // Take care of hash container invariant (there has to be at least one empty slot to ensure 79 | // the lookup loop finds either the element or an empty slot). 80 | return Math.min(arraySize - 1, (int) Math.ceil(arraySize * loadFactor)); 81 | } 82 | 83 | /** */ 84 | static void checkLoadFactor(double loadFactor, double minAllowedInclusive, double maxAllowedInclusive) { 85 | if (loadFactor < minAllowedInclusive || loadFactor > maxAllowedInclusive) { 86 | throw new BufferAllocationException( 87 | "The load factor should be in range [%.2f, %.2f]: %f", 88 | minAllowedInclusive, 89 | maxAllowedInclusive, 90 | loadFactor); 91 | } 92 | } 93 | 94 | /** */ 95 | static boolean checkPowerOfTwo(int arraySize) { 96 | // These are internals, we can just assert without retrying. 97 | assert arraySize > 1; 98 | assert BitUtil.nextHighestPowerOfTwo(arraySize) == arraySize; 99 | return true; 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /hppc/src/main/java/com/carrotsearch/hppc/BoundedProportionalArraySizingStrategy.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc; 2 | 3 | import java.util.ArrayList; 4 | 5 | /** 6 | * Array resizing proportional to the current buffer size, optionally kept 7 | * within the given minimum and maximum growth limits. Java's {@link ArrayList} 8 | * uses: 9 | * 10 | *
11 |  * minGrow = 1
12 |  * maxGrow = Integer.MAX_VALUE (unbounded)
13 |  * growRatio = 1.5f
14 |  * 
15 | */ 16 | public final class BoundedProportionalArraySizingStrategy implements ArraySizingStrategy { 17 | /** 18 | * Maximum allocable array length (approximately the largest positive integer 19 | * decreased by the array's object header). 20 | */ 21 | public static final int MAX_ARRAY_LENGTH = Integer.MAX_VALUE - /* aligned array header + slack */32; 22 | 23 | /** Minimum grow count. */ 24 | public final static int DEFAULT_MIN_GROW_COUNT = 10; 25 | 26 | /** Maximum grow count (unbounded). */ 27 | public final static int DEFAULT_MAX_GROW_COUNT = MAX_ARRAY_LENGTH; 28 | 29 | /** Default resize is by half the current buffer's size. */ 30 | public final static float DEFAULT_GROW_RATIO = 1.5f; 31 | 32 | /** Minimum number of elements to grow, if limit exceeded. */ 33 | public final int minGrowCount; 34 | 35 | /** Maximum number of elements to grow, if limit exceeded. */ 36 | public final int maxGrowCount; 37 | 38 | /** 39 | * The current buffer length is multiplied by this ratio to get the first 40 | * estimate for the new size. To double the size of the current buffer, for 41 | * example, set to 2. 42 | */ 43 | public final float growRatio; 44 | 45 | /** 46 | * Create the default sizing strategy. 47 | */ 48 | public BoundedProportionalArraySizingStrategy() { 49 | this(DEFAULT_MIN_GROW_COUNT, DEFAULT_MAX_GROW_COUNT, DEFAULT_GROW_RATIO); 50 | } 51 | 52 | /** 53 | * Create the sizing strategy with custom policies. 54 | * 55 | * @param minGrow Minimum number of elements to grow by when expanding. 56 | * @param maxGrow Maximum number of elements to grow by when expanding. 57 | * @param ratio The ratio of expansion compared to the previous buffer size. 58 | */ 59 | public BoundedProportionalArraySizingStrategy(int minGrow, int maxGrow, float ratio) { 60 | assert minGrow >= 1 : "Min grow must be >= 1."; 61 | assert maxGrow >= minGrow : "Max grow must be >= min grow."; 62 | assert ratio >= 1f : "Growth ratio must be >= 1 (was " + ratio + ")."; 63 | 64 | this.minGrowCount = minGrow; 65 | this.maxGrowCount = maxGrow; 66 | this.growRatio = ratio - 1.0f; 67 | } 68 | 69 | /** 70 | * Grow according to {@link #growRatio}, {@link #minGrowCount} and 71 | * {@link #maxGrowCount}. 72 | * 73 | * @param currentBufferLength The current length of the buffer. 74 | * @param elementsCount The number of elements stored in the buffer. 75 | * @param expectedAdditions The number of expected additions to the buffer. 76 | * @return New buffer size. 77 | */ 78 | public int grow(int currentBufferLength, int elementsCount, int expectedAdditions) { 79 | long growBy = (long) ((long) currentBufferLength * growRatio); 80 | growBy = Math.max(growBy, minGrowCount); 81 | growBy = Math.min(growBy, maxGrowCount); 82 | long growTo = Math.min(MAX_ARRAY_LENGTH, growBy + currentBufferLength); 83 | long newSize = Math.max((long) elementsCount + expectedAdditions, growTo); 84 | 85 | if (newSize > MAX_ARRAY_LENGTH) { 86 | throw new BufferAllocationException( 87 | "Java array size exceeded (current length: %d, elements: %d, expected additions: %d)", currentBufferLength, 88 | elementsCount, expectedAdditions); 89 | } 90 | 91 | return (int) newSize; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /hppc/src/test/java/com/carrotsearch/hppc/NaNCornerCaseTest.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Test; 5 | 6 | public class NaNCornerCaseTest 7 | { 8 | /** @see "http://issues.carrot2.org/browse/HPPC-93" */ 9 | @Test 10 | public void testNaNAsDoubleKey() 11 | { 12 | DoubleObjectMap map = new DoubleObjectHashMap<>(); 13 | map.put(Double.NaN, "a"); 14 | map.put(Double.NaN, "b"); 15 | 16 | Assert.assertEquals(1, map.size()); 17 | Assert.assertEquals("b", map.get(Double.NaN)); 18 | 19 | map.put(Double.longBitsToDouble(0xfff8000000000000L), "c"); 20 | Assert.assertEquals(1, map.size()); 21 | Assert.assertEquals("c", map.get(Double.NaN)); 22 | Assert.assertEquals( 23 | (Double) map.keys().iterator().next().value, 24 | (Double) Double.NaN); 25 | 26 | DoubleHashSet set = new DoubleHashSet(); 27 | set.add(Double.NaN); 28 | set.add(Double.NaN); 29 | set.add(Double.longBitsToDouble(0xfff8000000000000L)); 30 | Assert.assertEquals(1, set.size()); 31 | Assert.assertEquals( 32 | (Double) set.iterator().next().value, 33 | (Double) Double.NaN); 34 | } 35 | 36 | /** @see "http://issues.carrot2.org/browse/HPPC-93" */ 37 | @Test 38 | public void testNaNAsFloatKey() 39 | { 40 | FloatObjectMap map = new FloatObjectHashMap<>(); 41 | map.put(Float.NaN, "a"); 42 | map.put(Float.NaN, "b"); 43 | 44 | Assert.assertEquals(1, map.size()); 45 | Assert.assertEquals("b", map.get(Float.NaN)); 46 | 47 | map.put(Float.intBitsToFloat(0xfff80000), "c"); 48 | Assert.assertEquals(1, map.size()); 49 | Assert.assertEquals("c", map.get(Float.NaN)); 50 | Assert.assertEquals( 51 | (Float) map.keys().iterator().next().value, 52 | (Float) Float.NaN); 53 | 54 | FloatHashSet set = new FloatHashSet(); 55 | set.add(Float.NaN); 56 | set.add(Float.NaN); 57 | set.add(Float.intBitsToFloat(0xfff80000)); 58 | Assert.assertEquals(1, set.size()); 59 | Assert.assertEquals( 60 | (Float) set.iterator().next().value, 61 | (Float) Float.NaN); 62 | } 63 | 64 | /** @see "http://issues.carrot2.org/browse/HPPC-93" */ 65 | @Test 66 | public void testNaNAsValue() 67 | { 68 | { 69 | IntDoubleMap m1 = new IntDoubleHashMap(); 70 | m1.put(1, Double.NaN); 71 | IntDoubleMap m2 = new IntDoubleHashMap(); 72 | m2.put(1, Double.NaN); 73 | Assert.assertEquals(m1, m2); 74 | } 75 | 76 | { 77 | IntFloatMap m1 = new IntFloatHashMap(); 78 | m1.put(1, Float.NaN); 79 | IntFloatMap m2 = new IntFloatHashMap(); 80 | m2.put(1, Float.NaN); 81 | Assert.assertEquals(m1, m2); 82 | } 83 | 84 | { 85 | FloatArrayList list = new FloatArrayList(); 86 | Assert.assertFalse(list.contains(Float.NaN)); 87 | list.add(0, Float.NaN, 1); 88 | Assert.assertTrue(list.contains(Float.NaN)); 89 | } 90 | 91 | { 92 | DoubleArrayList list = new DoubleArrayList(); 93 | Assert.assertFalse(list.contains(Double.NaN)); 94 | list.add(0, Double.NaN, 1); 95 | Assert.assertTrue(list.contains(Double.NaN)); 96 | } 97 | 98 | { 99 | 100 | DoubleArrayList l1 = new DoubleArrayList(); 101 | l1.add(0, Double.NaN, 1); 102 | DoubleArrayList l2 = new DoubleArrayList(); 103 | l2.add(0, Double.NaN, 1); 104 | Assert.assertEquals(l1, l2); 105 | } 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /hppc/src/main/templates/com/carrotsearch/hppc/KTypeContainer.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc; 2 | 3 | import java.util.Iterator; 4 | 5 | import com.carrotsearch.hppc.cursors.KTypeCursor; 6 | import com.carrotsearch.hppc.predicates.KTypePredicate; 7 | import com.carrotsearch.hppc.procedures.KTypeProcedure; 8 | 9 | /** 10 | * A generic container holding KTypes. 11 | */ 12 | /*! ${TemplateOptions.generatedAnnotation} !*/ 13 | public interface KTypeContainer extends Iterable> { 14 | /** 15 | * Returns an iterator to a cursor traversing the collection. The order of 16 | * traversal is not defined. More than one cursor may be active at a time. The 17 | * behavior of iterators is undefined if structural changes are made to the 18 | * underlying collection. 19 | * 20 | *

21 | * The iterator is implemented as a cursor and it returns the same cursor 22 | * instance on every call to {@link Iterator#next()} (to avoid boxing of 23 | * primitive types). To read the current list's value (or index in the list) 24 | * use the cursor's public fields. An example is shown below. 25 | *

26 | * 27 | *
 28 |    * for (KTypeCursor<KType> c : container) {
 29 |    *   System.out.println("index=" + c.index + " value=" + c.value);
 30 |    * }
 31 |    * 
32 | */ 33 | public Iterator> iterator(); 34 | 35 | /** 36 | * Lookup a given element in the container. This operation has no speed 37 | * guarantees (may be linear with respect to the size of this container). 38 | * 39 | * @return Returns true if this container has an element equal to 40 | * e. 41 | */ 42 | public boolean contains(KType e); 43 | 44 | /** 45 | * Return the current number of elements in this container. The time for 46 | * calculating the container's size may take O(n) time, although 47 | * implementing classes should try to maintain the current size and return in 48 | * constant time. 49 | */ 50 | public int size(); 51 | 52 | /** 53 | * Shortcut for size() == 0. 54 | */ 55 | public boolean isEmpty(); 56 | 57 | /** 58 | * Copies all elements of this container to an array. 59 | * 60 | * The returned array is always a copy, regardless of the storage used by the 61 | * container. 62 | */ 63 | /*! #if ($TemplateOptions.KTypePrimitive) 64 | public KType [] toArray(); 65 | #else !*/ 66 | public Object[] toArray(); 67 | /*! #end !*/ 68 | 69 | /* #if ($TemplateOptions.KTypeGeneric) */ 70 | /** 71 | * Copies all elements of this container to a dynamically created array of the 72 | * given component type. 73 | * 74 | * @throws ArrayStoreException Thrown if this container's elements are not 75 | * assignable to the array's component type. 76 | */ 77 | public T[] toArray(Class componentClass); 78 | /* #end */ 79 | 80 | /** 81 | * Applies a procedure to all container elements. Returns the 82 | * argument (any subclass of {@link KTypeProcedure}. This lets the caller to 83 | * call methods of the argument by chaining the call (even if the argument is 84 | * an anonymous type) to retrieve computed values, for example (IntContainer): 85 | * 86 | *
 87 |    * int count = container.forEach(new IntProcedure() {
 88 |    *   int count; // this is a field declaration in an anonymous class.
 89 |    * 
 90 |    *   public void apply(int value) {
 91 |    *     count++;
 92 |    *   }
 93 |    * }).count;
 94 |    * 
95 | */ 96 | public > T forEach(T procedure); 97 | 98 | /** 99 | * Applies a predicate to container elements as long, as the 100 | * predicate returns true. The iteration is interrupted 101 | * otherwise. 102 | */ 103 | public > T forEach(T predicate); 104 | } 105 | -------------------------------------------------------------------------------- /hppc-benchmarks/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 4.0.0 5 | 6 | 7 | com.carrotsearch 8 | hppc-parent 9 | 0.8.0-SNAPSHOT 10 | ../pom.xml 11 | 12 | 13 | hppc-benchmarks 14 | jar 15 | 16 | HPPC Benchmarks 17 | 18 | 19 | 20 | com.carrotsearch 21 | hppc 22 | ${project.version} 23 | 24 | 25 | 26 | com.carrotsearch 27 | hppc 28 | ${project.version} 29 | esoteric 30 | 31 | 32 | 33 | it.unimi.dsi 34 | fastutil 35 | ${version.fastutil} 36 | 37 | 38 | 39 | net.openhft 40 | koloboke-impl-jdk6-7 41 | ${version.koloboke} 42 | 43 | 44 | 45 | org.openjdk.jmh 46 | jmh-core 47 | ${version.jmh} 48 | 49 | 50 | 51 | org.openjdk.jmh 52 | jmh-generator-annprocess 53 | ${version.jmh} 54 | provided 55 | 56 | 57 | 58 | 59 | true 60 | true 61 | 62 | 63 | 64 | verify 65 | 66 | 67 | 68 | org.apache.maven.plugins 69 | maven-shade-plugin 70 | ${version.maven-shade-plugin} 71 | 72 | 73 | shade-jmh 74 | package 75 | 76 | shade 77 | 78 | 79 | benchmarks 80 | 81 | 82 | org.openjdk.jmh.Main 83 | 84 | 85 | 86 | 87 | *:* 88 | 89 | META-INF/*.SF 90 | META-INF/*.DSA 91 | META-INF/*.RSA 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | eclipse 105 | 106 | 107 | m2e.version 108 | 109 | 110 | 111 | 112 | 113 | 114 | org.apache.maven.plugins 115 | maven-shade-plugin 116 | ${version.maven-shade-plugin} 117 | 118 | 119 | shade-jmh 120 | none 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | -------------------------------------------------------------------------------- /hppc-template-processor/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | 6 | com.carrotsearch 7 | hppc-parent 8 | 0.8.0-SNAPSHOT 9 | ../pom.xml 10 | 11 | 12 | hppc-template-processor 13 | maven-plugin 14 | 15 | HPPC Template Processor 16 | Template Processor and Code Generation for HPPC. 17 | 18 | 19 | 20 | com.google.guava 21 | guava 22 | 23 | 24 | 25 | org.apache.velocity 26 | velocity 27 | ${version.velocity} 28 | 29 | 30 | 31 | org.antlr 32 | antlr4 33 | ${version.antlr} 34 | 35 | 36 | 37 | org.apache.maven 38 | maven-plugin-api 39 | ${version.maven.api} 40 | 41 | 42 | 43 | org.apache.maven 44 | maven-core 45 | ${version.maven.api} 46 | 47 | 48 | 49 | org.apache.maven.plugin-tools 50 | maven-plugin-annotations 51 | 3.4 52 | provided 53 | 54 | 55 | 56 | com.carrotsearch.randomizedtesting 57 | randomizedtesting-runner 58 | test 59 | 60 | 61 | 62 | junit 63 | junit 64 | 65 | 66 | 67 | org.assertj 68 | assertj-core 69 | test 70 | 71 | 72 | 73 | 74 | 75 | 76 | org.antlr 77 | antlr4-maven-plugin 78 | 79 | 80 | antlr4 81 | 82 | antlr4 83 | 84 | 85 | true 86 | 87 | 88 | 89 | 90 | 91 | 92 | org.apache.maven.plugins 93 | maven-plugin-plugin 94 | 3.4 95 | 96 | 97 | java-annotations 98 | 99 | 100 | 101 | 102 | mojo-descriptor 103 | process-classes 104 | 105 | descriptor 106 | 107 | 108 | 109 | 110 | generated-helpmojo 111 | 112 | helpmojo 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | eclipse 123 | 124 | 125 | m2e.version 126 | 127 | 128 | 129 | false 130 | false 131 | 132 | 133 | 134 | 135 | -------------------------------------------------------------------------------- /hppc/src/main/java/com/carrotsearch/hppc/BitUtil.java: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Repackaged from org.apache.lucene.util.OpenBitSet (Lucene). 4 | * svn rev. 1479633, https://svn.apache.org/repos/asf/lucene/dev/trunk 5 | * 6 | * Minor changes in class hierarchy, removed serialization. 7 | */ 8 | 9 | 10 | /** 11 | * Licensed to the Apache Software Foundation (ASF) under one or more 12 | * contributor license agreements. See the NOTICE file distributed with 13 | * this work for additional information regarding copyright ownership. 14 | * The ASF licenses this file to You under the Apache License, Version 2.0 15 | * (the "License"); you may not use this file except in compliance with 16 | * the License. You may obtain a copy of the License at 17 | * 18 | * http://www.apache.org/licenses/LICENSE-2.0 19 | * 20 | * Unless required by applicable law or agreed to in writing, software 21 | * distributed under the License is distributed on an "AS IS" BASIS, 22 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 23 | * See the License for the specific language governing permissions and 24 | * limitations under the License. 25 | */ 26 | 27 | package com.carrotsearch.hppc; 28 | 29 | /** 30 | * A variety of high efficiency bit twiddling routines. 31 | */ 32 | final class BitUtil { 33 | private BitUtil() {} // no instance 34 | 35 | // The pop methods used to rely on bit-manipulation tricks for speed but it 36 | // turns out that it is faster to use the Long.bitCount method (which is an 37 | // intrinsic since Java 6u18) in a naive loop, see LUCENE-2221 38 | 39 | /** Returns the number of set bits in an array of longs. */ 40 | public static long pop_array(long[] arr, int wordOffset, int numWords) { 41 | long popCount = 0; 42 | for (int i = wordOffset, end = wordOffset + numWords; i < end; ++i) { 43 | popCount += Long.bitCount(arr[i]); 44 | } 45 | return popCount; 46 | } 47 | 48 | /** Returns the popcount or cardinality of the two sets after an intersection. 49 | * Neither array is modified. */ 50 | public static long pop_intersect(long[] arr1, long[] arr2, int wordOffset, int numWords) { 51 | long popCount = 0; 52 | for (int i = wordOffset, end = wordOffset + numWords; i < end; ++i) { 53 | popCount += Long.bitCount(arr1[i] & arr2[i]); 54 | } 55 | return popCount; 56 | } 57 | 58 | /** Returns the popcount or cardinality of the union of two sets. 59 | * Neither array is modified. */ 60 | public static long pop_union(long[] arr1, long[] arr2, int wordOffset, int numWords) { 61 | long popCount = 0; 62 | for (int i = wordOffset, end = wordOffset + numWords; i < end; ++i) { 63 | popCount += Long.bitCount(arr1[i] | arr2[i]); 64 | } 65 | return popCount; 66 | } 67 | 68 | /** Returns the popcount or cardinality of A & ~B. 69 | * Neither array is modified. */ 70 | public static long pop_andnot(long[] arr1, long[] arr2, int wordOffset, int numWords) { 71 | long popCount = 0; 72 | for (int i = wordOffset, end = wordOffset + numWords; i < end; ++i) { 73 | popCount += Long.bitCount(arr1[i] & ~arr2[i]); 74 | } 75 | return popCount; 76 | } 77 | 78 | /** Returns the popcount or cardinality of A ^ B 79 | * Neither array is modified. */ 80 | public static long pop_xor(long[] arr1, long[] arr2, int wordOffset, int numWords) { 81 | long popCount = 0; 82 | for (int i = wordOffset, end = wordOffset + numWords; i < end; ++i) { 83 | popCount += Long.bitCount(arr1[i] ^ arr2[i]); 84 | } 85 | return popCount; 86 | } 87 | 88 | /** returns the next highest power of two, or the current value if it's already a power of two or zero*/ 89 | public static int nextHighestPowerOfTwo(int v) { 90 | v--; 91 | v |= v >> 1; 92 | v |= v >> 2; 93 | v |= v >> 4; 94 | v |= v >> 8; 95 | v |= v >> 16; 96 | v++; 97 | return v; 98 | } 99 | 100 | /** returns the next highest power of two, or the current value if it's already a power of two or zero*/ 101 | public static long nextHighestPowerOfTwo(long v) { 102 | v--; 103 | v |= v >> 1; 104 | v |= v >> 2; 105 | v |= v >> 4; 106 | v |= v >> 8; 107 | v |= v >> 16; 108 | v |= v >> 32; 109 | v++; 110 | return v; 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /hppc/src/main/java/com/carrotsearch/hppc/sorting/IndirectSort.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc.sorting; 2 | 3 | import java.util.Comparator; 4 | 5 | /** 6 | * Sorting routines that return an array of sorted indices implied by a given 7 | * comparator rather than move elements of whatever the comparator is using for 8 | * comparisons. 9 | *

10 | * A practical use case for this class is when the index of an array is 11 | * meaningful and one wants to acquire the order of values in that array. None 12 | * of the methods in Java Collections would provide such functionality directly 13 | * and creating a collection of boxed {@link Integer} objects for indices seems 14 | * to be too costly. 15 | */ 16 | public final class IndirectSort { 17 | /** 18 | * Minimum window length to apply insertion sort in merge sort. 19 | */ 20 | static int MIN_LENGTH_FOR_INSERTION_SORT = 30; 21 | 22 | /** 23 | * No instantiation. 24 | */ 25 | private IndirectSort() { 26 | // No instantiation. 27 | } 28 | 29 | /** 30 | * Returns the order of elements between indices start and 31 | * length, as indicated by the given comparator. 32 | *

33 | * This routine uses merge sort. It is guaranteed to be stable. 34 | *

35 | */ 36 | public static int[] mergesort(int start, int length, IndirectComparator comparator) { 37 | final int[] src = createOrderArray(start, length); 38 | 39 | if (length > 1) { 40 | final int[] dst = (int[]) src.clone(); 41 | topDownMergeSort(src, dst, 0, length, comparator); 42 | return dst; 43 | } 44 | 45 | return src; 46 | } 47 | 48 | /** 49 | * Returns the order of elements between indices start and 50 | * length, as indicated by the given comparator. 51 | * This method is equivalent to calling 52 | * {@link #mergesort(int, int, IndirectComparator)} with 53 | * {@link IndirectComparator.DelegatingComparator}. 54 | *

55 | * This routine uses merge sort. It is guaranteed to be stable. 56 | *

57 | */ 58 | public static int[] mergesort(T[] input, int start, int length, Comparator comparator) { 59 | return mergesort(start, length, new IndirectComparator.DelegatingComparator(input, comparator)); 60 | } 61 | 62 | /** 63 | * Perform a recursive, descending merge sort. 64 | * 65 | * @param fromIndex 66 | * inclusive 67 | * @param toIndex 68 | * exclusive 69 | */ 70 | private static void topDownMergeSort(int[] src, int[] dst, int fromIndex, int toIndex, IndirectComparator comp) { 71 | if (toIndex - fromIndex <= MIN_LENGTH_FOR_INSERTION_SORT) { 72 | insertionSort(fromIndex, toIndex - fromIndex, dst, comp); 73 | return; 74 | } 75 | 76 | final int mid = (fromIndex + toIndex) >>> 1; 77 | topDownMergeSort(dst, src, fromIndex, mid, comp); 78 | topDownMergeSort(dst, src, mid, toIndex, comp); 79 | 80 | /* 81 | * Both splits in of src are now sorted. 82 | */ 83 | if (comp.compare(src[mid - 1], src[mid]) <= 0) { 84 | /* 85 | * If the lowest element in upper slice is larger than the highest element in 86 | * the lower slice, simply copy over, the data is fully sorted. 87 | */ 88 | System.arraycopy(src, fromIndex, dst, fromIndex, toIndex - fromIndex); 89 | } else { 90 | /* 91 | * Run a manual merge. 92 | */ 93 | for (int i = fromIndex, j = mid, k = fromIndex; k < toIndex; k++) { 94 | if (j == toIndex || (i < mid && comp.compare(src[i], src[j]) <= 0)) { 95 | dst[k] = src[i++]; 96 | } else { 97 | dst[k] = src[j++]; 98 | } 99 | } 100 | } 101 | } 102 | 103 | /** 104 | * Internal insertion sort for ints. 105 | */ 106 | private static void insertionSort(final int off, final int len, int[] order, IndirectComparator intComparator) { 107 | for (int i = off + 1; i < off + len; i++) { 108 | final int v = order[i]; 109 | int j = i, t; 110 | while (j > off && intComparator.compare(t = order[j - 1], v) > 0) { 111 | order[j--] = t; 112 | } 113 | order[j] = v; 114 | } 115 | } 116 | 117 | /** 118 | * Creates the initial order array. 119 | */ 120 | private static int[] createOrderArray(final int start, final int length) { 121 | final int[] order = new int[length]; 122 | for (int i = 0; i < length; i++) { 123 | order[i] = start + i; 124 | } 125 | return order; 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /hppc-template-processor/src/main/java/com/carrotsearch/hppc/generator/parser/SignatureProcessor.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc.generator.parser; 2 | 3 | import java.io.IOException; 4 | import java.io.StringWriter; 5 | import java.io.Writer; 6 | import java.util.ArrayList; 7 | import java.util.Collection; 8 | import java.util.Collections; 9 | import java.util.Comparator; 10 | import java.util.List; 11 | 12 | import org.antlr.v4.runtime.ANTLRInputStream; 13 | import org.antlr.v4.runtime.BailErrorStrategy; 14 | import org.antlr.v4.runtime.BufferedTokenStream; 15 | import org.antlr.v4.runtime.CommonTokenStream; 16 | import org.antlr.v4.runtime.Lexer; 17 | import org.antlr.v4.runtime.Token; 18 | 19 | import com.carrotsearch.hppc.generator.TemplateOptions; 20 | import com.carrotsearch.hppc.generator.parser.Java7Parser.CompilationUnitContext; 21 | 22 | /** */ 23 | public class SignatureProcessor { 24 | final Java7Parser parser; 25 | final CommonTokenStream tokenStream; 26 | final CompilationUnitContext unitContext; 27 | 28 | public SignatureProcessor(String input) { 29 | Lexer lexer = new Java7Lexer(new ANTLRInputStream(input)); 30 | tokenStream = new CommonTokenStream(lexer); 31 | parser = new Java7Parser(tokenStream); 32 | parser.setErrorHandler(new BailErrorStrategy()); 33 | unitContext = parser.compilationUnit(); 34 | } 35 | 36 | /* 37 | * 38 | */ 39 | public String process(TemplateOptions templateOptions) throws IOException { 40 | return applyReplacements(findReplacements(templateOptions), templateOptions); 41 | } 42 | 43 | /* 44 | * 45 | */ 46 | private List findReplacements(TemplateOptions templateOptions) { 47 | List replacements = unitContext.accept(new SignatureReplacementVisitor(templateOptions, this)); 48 | return replacements; 49 | } 50 | 51 | /* 52 | * 53 | */ 54 | private String applyReplacements(List replacements, TemplateOptions options) throws IOException { 55 | StringWriter sw = new StringWriter(); 56 | reconstruct(sw, tokenStream, 0, tokenStream.size() - 1, replacements, options); 57 | return sw.toString(); 58 | } 59 | 60 | /** 61 | * Process references inside comment blocks, javadocs, etc. 62 | */ 63 | private String processComment(String text, TemplateOptions options) { 64 | if (options.hasKType()) { 65 | text = text.replaceAll("(KType)(?=\\p{Lu})", options.getKType().getBoxedType()); 66 | text = text.replace("KType", options.getKType().getType()); 67 | } 68 | if (options.hasVType()) { 69 | text = text.replaceAll("(VType)(?=\\p{Lu})", options.getVType().getBoxedType()); 70 | text = text.replace("VType", options.getVType().getType()); 71 | } 72 | return text; 73 | } 74 | 75 | /* 76 | * 77 | */ 78 | T reconstruct( 79 | T sw, 80 | BufferedTokenStream tokenStream, 81 | int from, int to, 82 | Collection replacements, 83 | TemplateOptions templateOptions) throws IOException { 84 | 85 | ArrayList sorted = new ArrayList<>(replacements); 86 | Collections.sort(sorted, new Comparator() { 87 | @Override 88 | public int compare(Replacement a, Replacement b) { 89 | return Integer.compare(a.interval.a, b.interval.b); 90 | } 91 | }); 92 | 93 | for (int i = 1; i < sorted.size(); i++) { 94 | Replacement previous = sorted.get(i - 1); 95 | Replacement current = sorted.get(i); 96 | if (!previous.interval.startsBeforeDisjoint(current.interval)) { 97 | throw new RuntimeException("Overlapping intervals: " + previous + " " + current); 98 | } 99 | } 100 | 101 | int left = from; 102 | for (Replacement r : sorted) { 103 | int right = r.interval.a; 104 | for (int i = left; i < right; i++) { 105 | sw.append(tokenText(templateOptions, tokenStream.get(i))); 106 | } 107 | sw.append(r.replacement); 108 | left = r.interval.b + 1; 109 | } 110 | 111 | for (int i = left; i < to; i++) { 112 | sw.append(tokenText(templateOptions, tokenStream.get(i))); 113 | } 114 | return sw; 115 | } 116 | 117 | protected String tokenText(TemplateOptions templateOptions, Token token) { 118 | String text = token.getText(); 119 | if (token.getChannel() == Java7Lexer.CHANNEL_COMMENT) { 120 | text = processComment(text, templateOptions); 121 | } 122 | return text; 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /hppc/src/main/templates/com/carrotsearch/hppc/KTypeVTypeIdentityHashMap.java: -------------------------------------------------------------------------------- 1 | /*! #set($TemplateOptions.ignored = ($TemplateOptions.KTypePrimitive)) !*/ 2 | package com.carrotsearch.hppc; 3 | 4 | /* #if ($TemplateOptions.VTypeGeneric) */ 5 | import java.util.Iterator; 6 | import com.carrotsearch.hppc.cursors.*; 7 | /* #end */ 8 | 9 | import static com.carrotsearch.hppc.Containers.*; 10 | import static com.carrotsearch.hppc.HashContainers.*; 11 | 12 | /** 13 | * An identity hash map of KType to VType. 14 | */ 15 | /*! #if ($TemplateOptions.anyGeneric) @SuppressWarnings("all") #end !*/ 16 | /*! ${TemplateOptions.generatedAnnotation} !*/ 17 | public class KTypeVTypeIdentityHashMap 18 | extends KTypeVTypeHashMap 19 | { 20 | /** 21 | * New instance with sane defaults. 22 | */ 23 | public KTypeVTypeIdentityHashMap() { 24 | this(DEFAULT_EXPECTED_ELEMENTS); 25 | } 26 | 27 | /** 28 | * New instance with sane defaults. 29 | * @param expectedElements 30 | * The expected number of elements guaranteed not to cause buffer 31 | * expansion (inclusive). 32 | */ 33 | public KTypeVTypeIdentityHashMap(int expectedElements) { 34 | this(expectedElements, DEFAULT_LOAD_FACTOR); 35 | } 36 | 37 | /** 38 | * New instance with sane defaults. 39 | * 40 | * @param expectedElements 41 | * The expected number of elements guaranteed not to cause buffer 42 | * expansion (inclusive). 43 | * @param loadFactor 44 | * The load factor for internal buffers. Insane load factors (zero, full capacity) 45 | * are rejected by {@link #verifyLoadFactor(double)}. 46 | */ 47 | public KTypeVTypeIdentityHashMap(int expectedElements, double loadFactor) { 48 | this(expectedElements, loadFactor, HashOrderMixing.randomized()); 49 | } 50 | 51 | /** 52 | * New instance with the provided defaults. 53 | * 54 | * @param expectedElements 55 | * The expected number of elements guaranteed not to cause a rehash (inclusive). 56 | * @param loadFactor 57 | * The load factor for internal buffers. Insane load factors (zero, full capacity) 58 | * are rejected by {@link #verifyLoadFactor(double)}. 59 | * @param orderMixer 60 | * Hash key order mixing strategy. See {@link HashOrderMixing} for predefined 61 | * implementations. Use constant mixers only if you understand the potential 62 | * consequences. 63 | */ 64 | public KTypeVTypeIdentityHashMap(int expectedElements, double loadFactor, HashOrderMixingStrategy orderMixer) { 65 | this.orderMixer = orderMixer; 66 | this.loadFactor = verifyLoadFactor(loadFactor); 67 | ensureCapacity(expectedElements); 68 | } 69 | 70 | /** 71 | * Create a hash map from all key-value pairs of another container. 72 | */ 73 | public KTypeVTypeIdentityHashMap(KTypeVTypeAssociativeContainer container) { 74 | this(container.size()); 75 | putAll(container); 76 | } 77 | 78 | @Override 79 | public int hashKey(KType key) { 80 | assert !Intrinsics. isEmpty(key); // Handled as a special case (empty slot marker). 81 | return BitMixer.mix(System.identityHashCode(key), this.keyMixer); 82 | } 83 | 84 | @Override 85 | public boolean equals(Object v1, Object v2) { 86 | return v1 == v2; 87 | } 88 | 89 | /* #if ($TemplateOptions.VTypeGeneric) */ 90 | @Override 91 | protected boolean equalElements(KTypeVTypeHashMap other) { 92 | if (other.size() != size()) { 93 | return false; 94 | } 95 | 96 | Iterator> i = other.iterator(); 97 | while (i.hasNext()) { 98 | KTypeVTypeCursor c = i.next(); 99 | KType key = Intrinsics. cast(c.key); 100 | if (!containsKey(key) || 101 | !equals(get(key), c.value)) { // Compare values using the same function as keys. 102 | return false; 103 | } 104 | } 105 | 106 | return true; 107 | } 108 | /* #end */ 109 | 110 | /** 111 | * Creates a hash map from two index-aligned arrays of key-value pairs. 112 | */ 113 | public static KTypeVTypeIdentityHashMap from(KType[] keys, VType[] values) { 114 | if (keys.length != values.length) { 115 | throw new IllegalArgumentException("Arrays of keys and values must have an identical length."); 116 | } 117 | 118 | KTypeVTypeIdentityHashMap map = new KTypeVTypeIdentityHashMap<>(keys.length); 119 | for (int i = 0; i < keys.length; i++) { 120 | map.put(keys[i], values[i]); 121 | } 122 | 123 | return map; 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /hppc/src/main/templates/com/carrotsearch/hppc/KTypeVTypeAssociativeContainer.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc; 2 | 3 | import java.util.Iterator; 4 | 5 | import com.carrotsearch.hppc.cursors.*; 6 | import com.carrotsearch.hppc.predicates.*; 7 | import com.carrotsearch.hppc.procedures.*; 8 | 9 | /** 10 | * An associative container from keys to (one or 11 | * possibly more) values. 12 | * 13 | * @see KTypeContainer 14 | */ 15 | /*! ${TemplateOptions.generatedAnnotation} !*/ 16 | public interface KTypeVTypeAssociativeContainer 17 | extends Iterable> 18 | { 19 | /** 20 | * Returns a cursor over the entries (key-value pairs) in this map. The 21 | * iterator is implemented as a cursor and it returns the same cursor 22 | * instance on every call to {@link Iterator#next()}. To read the current 23 | * key and value use the cursor's public fields. An example is shown below. 24 | * 25 | *
 26 |    * for (IntShortCursor c : intShortMap) {
 27 |    *   System.out.println("index=" + c.index + " key=" + c.key + " value=" + c.value);
 28 |    * }
29 | * 30 | *

31 | * The index field inside the cursor gives the internal index 32 | * inside the container's implementation. The interpretation of this index 33 | * depends on to the container. 34 | */ 35 | @Override 36 | public Iterator> iterator(); 37 | 38 | /** 39 | * Returns true if this container has an association to a value 40 | * for the given key. 41 | */ 42 | public boolean containsKey(KType key); 43 | 44 | /** 45 | * @return Returns the current size (number of assigned keys) in the 46 | * container. 47 | */ 48 | public int size(); 49 | 50 | /** 51 | * @return Return true if this hash map contains no assigned 52 | * keys. 53 | */ 54 | public boolean isEmpty(); 55 | 56 | /** 57 | * Removes all keys (and associated values) present in a given container. An 58 | * alias to: 59 | * 60 | *

 61 |    * keys().removeAll(container)
 62 |    * 
63 | * 64 | * but with no additional overhead. 65 | * 66 | * @return Returns the number of elements actually removed as a result of this 67 | * call. 68 | */ 69 | public int removeAll(KTypeContainer container); 70 | 71 | /** 72 | * Removes all keys (and associated values) for which the predicate returns 73 | * true. 74 | * 75 | * @return Returns the number of elements actually removed as a result of this 76 | * call. 77 | */ 78 | public int removeAll(KTypePredicate predicate); 79 | 80 | /** 81 | * Removes all keys (and associated values) for which the predicate returns 82 | * true. 83 | * 84 | * @return Returns the number of elements actually removed as a result of this 85 | * call. 86 | */ 87 | public int removeAll(KTypeVTypePredicate predicate); 88 | 89 | /** 90 | * Applies a given procedure to all keys-value pairs in this container. 91 | * Returns the argument (any subclass of {@link KTypeVTypeProcedure}. This 92 | * lets the caller to call methods of the argument by chaining the call (even 93 | * if the argument is an anonymous type) to retrieve computed values, for 94 | * example. 95 | */ 96 | public > T forEach(T procedure); 97 | 98 | /** 99 | * Applies a given predicate to all keys-value pairs in this container. 100 | * Returns the argument (any subclass of {@link KTypeVTypePredicate}. This 101 | * lets the caller to call methods of the argument by chaining the call (even 102 | * if the argument is an anonymous type) to retrieve computed values, for 103 | * example. 104 | * 105 | * The iteration is continued as long as the predicate returns 106 | * true. 107 | */ 108 | public > T forEach(T predicate); 109 | 110 | /** 111 | * Returns a collection of keys of this container. The returned collection is 112 | * a view over the key set and any modifications (if allowed) introduced to 113 | * the collection will propagate to the associative container immediately. 114 | */ 115 | public KTypeCollection keys(); 116 | 117 | /** 118 | * Returns a container view of all values present in this container. The 119 | * returned collection is a view over the key set and any modifications (if 120 | * allowed) introduced to the collection will propagate to the associative 121 | * container immediately. 122 | */ 123 | public KTypeContainer values(); 124 | } 125 | -------------------------------------------------------------------------------- /hppc/src/main/java/com/carrotsearch/hppc/sorting/IndirectComparator.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc.sorting; 2 | 3 | import java.util.Comparator; 4 | 5 | /** 6 | * Compare objects at two given indices and return the result of their 7 | * comparison consistent with {@link Comparator}'s contract. 8 | *

9 | * Beware of the return (int - int) idiom, it is usually 10 | * broken if arbitrary numbers can appear on input. Use regular comparison 11 | * operations - they are very fast anyway. 12 | */ 13 | public interface IndirectComparator { 14 | /** 15 | * See class documentation. 16 | */ 17 | public int compare(int indexA, int indexB); 18 | 19 | /** 20 | * A natural-order comparator for integers. 21 | */ 22 | public static class AscendingIntComparator implements IndirectComparator { 23 | private final int[] array; 24 | 25 | public AscendingIntComparator(int[] array) { 26 | this.array = array; 27 | } 28 | 29 | public int compare(int indexA, int indexB) { 30 | final int a = array[indexA]; 31 | final int b = array[indexB]; 32 | 33 | if (a < b) 34 | return -1; 35 | if (a > b) 36 | return 1; 37 | return 0; 38 | } 39 | } 40 | 41 | /** 42 | * A reverse-order comparator for integers. 43 | */ 44 | public static class DescendingIntComparator extends AscendingIntComparator { 45 | public DescendingIntComparator(int[] array) { 46 | super(array); 47 | } 48 | 49 | public final int compare(int indexA, int indexB) { 50 | return -super.compare(indexA, indexB); 51 | } 52 | } 53 | 54 | /** 55 | * A natural-order comparator for integers. 56 | */ 57 | public static class AscendingShortComparator implements IndirectComparator { 58 | private final short[] array; 59 | 60 | public AscendingShortComparator(short[] array) { 61 | this.array = array; 62 | } 63 | 64 | public int compare(int indexA, int indexB) { 65 | final short a = array[indexA]; 66 | final short b = array[indexB]; 67 | 68 | if (a < b) 69 | return -1; 70 | if (a > b) 71 | return 1; 72 | return 0; 73 | } 74 | } 75 | 76 | /** 77 | * A reverse-order comparator for shorts. 78 | */ 79 | public static class DescendingShortComparator extends AscendingShortComparator { 80 | public DescendingShortComparator(short[] array) { 81 | super(array); 82 | } 83 | 84 | public final int compare(int indexA, int indexB) { 85 | return -super.compare(indexA, indexB); 86 | } 87 | } 88 | 89 | /** 90 | * A natural-order comparator for doubles. 91 | */ 92 | public static class AscendingDoubleComparator implements IndirectComparator { 93 | private final double[] array; 94 | 95 | public AscendingDoubleComparator(double[] array) { 96 | this.array = array; 97 | } 98 | 99 | public int compare(int indexA, int indexB) { 100 | final double a = array[indexA]; 101 | final double b = array[indexB]; 102 | 103 | if (a < b) 104 | return -1; 105 | if (a > b) 106 | return 1; 107 | return 0; 108 | } 109 | } 110 | 111 | /** 112 | * A reverse-order comparator for doubles. 113 | */ 114 | public static class DescendingDoubleComparator extends AscendingDoubleComparator { 115 | public DescendingDoubleComparator(double[] array) { 116 | super(array); 117 | } 118 | 119 | public final int compare(int indexA, int indexB) { 120 | return -super.compare(indexA, indexB); 121 | } 122 | } 123 | 124 | /** 125 | * A natural-order comparator for floats. 126 | */ 127 | public static class AscendingFloatComparator implements IndirectComparator { 128 | private final float[] array; 129 | 130 | public AscendingFloatComparator(float[] array) { 131 | this.array = array; 132 | } 133 | 134 | public int compare(int indexA, int indexB) { 135 | final float a = array[indexA]; 136 | final float b = array[indexB]; 137 | 138 | if (a < b) 139 | return -1; 140 | if (a > b) 141 | return 1; 142 | return 0; 143 | } 144 | } 145 | 146 | /** 147 | * A reverse-order comparator for floats. 148 | */ 149 | public static class DescendingFloatComparator extends AscendingFloatComparator { 150 | public DescendingFloatComparator(float[] array) { 151 | super(array); 152 | } 153 | 154 | public final int compare(int indexA, int indexB) { 155 | return -super.compare(indexA, indexB); 156 | } 157 | } 158 | 159 | /** 160 | * A delegating comparator for object types. 161 | */ 162 | public final static class DelegatingComparator implements IndirectComparator { 163 | private final T[] array; 164 | private final Comparator delegate; 165 | 166 | public DelegatingComparator(T[] array, Comparator delegate) { 167 | this.array = array; 168 | this.delegate = delegate; 169 | } 170 | 171 | public final int compare(int indexA, int indexB) { 172 | return delegate.compare(array[indexA], array[indexB]); 173 | } 174 | 175 | @Override 176 | public String toString() { 177 | return this.getClass().getSimpleName() + " -> " + delegate; 178 | } 179 | } 180 | } 181 | -------------------------------------------------------------------------------- /hppc/src/test/java/com/carrotsearch/hppc/HashCollisionsClusteringTest.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc; 2 | 3 | import java.util.Locale; 4 | import java.util.concurrent.TimeUnit; 5 | 6 | import org.junit.Test; 7 | 8 | import com.carrotsearch.hppc.cursors.IntCursor; 9 | import com.carrotsearch.randomizedtesting.RandomizedTest; 10 | 11 | public class HashCollisionsClusteringTest extends RandomizedTest 12 | { 13 | private static boolean debugging = false; 14 | 15 | /** @see "http://issues.carrot2.org/browse/HPPC-80" */ 16 | @Test 17 | public void testHashSetClusteringOnRehash() 18 | { 19 | IntHashSet source = new IntHashSet(0, 0.9d); 20 | for (int i = 1250000; i-- != 0;) { 21 | source.add(i); 22 | } 23 | 24 | IntHashSet target = new IntHashSet(0, 0.9d); 25 | int i = 0; 26 | long start = System.currentTimeMillis(); 27 | long deadline = start + TimeUnit.SECONDS.toMillis(3); 28 | for (IntCursor c : source) { 29 | target.add(c.value); 30 | if ((i++ % 5000) == 0) { 31 | System.out.println(String.format(Locale.ROOT, 32 | "Keys: %7d, %5d ms.", 33 | i, 34 | System.currentTimeMillis() - start)); 35 | 36 | if (System.currentTimeMillis() >= deadline) { 37 | fail("Takes too long, something is wrong. Added " + i + " keys out of " + source.size()); 38 | } 39 | } 40 | } 41 | } 42 | 43 | /** @see "http://issues.carrot2.org/browse/HPPC-80" */ 44 | @Test 45 | public void testHashMapClusteringOnRehash() 46 | { 47 | IntIntHashMap a = new IntIntHashMap(); 48 | for (int i = 10000000; i-- != 0;) { 49 | a.put(i, 0); 50 | } 51 | IntIntHashMap b2 = new IntIntHashMap(); 52 | b2.putAll(a); 53 | } 54 | 55 | /** */ 56 | @Test 57 | public void testHashSetClusteringAtFront() 58 | { 59 | int keys = 500000; 60 | IntHashSet target = new IntHashSet(keys, 0.9) { 61 | @Override 62 | protected void allocateBuffers(int arraySize) { 63 | super.allocateBuffers(arraySize); 64 | System.out.println("Rehashed to: " + arraySize); 65 | } 66 | }; 67 | 68 | int expandAtCount = HashContainers.expandAtCount(target.keys.length - 1, 0.9); 69 | int fillUntil = expandAtCount - 100000; 70 | 71 | IntHashSet source = new IntHashSet(keys, 0.9); 72 | int unique = 0; 73 | while (source.size() < expandAtCount - 1) { 74 | source.add(unique++); 75 | } 76 | System.out.println("Source filled up."); 77 | 78 | while (target.size() < fillUntil) { 79 | target.add(unique++); 80 | } 81 | System.out.println("Target filled up."); 82 | 83 | assertEquals(source.keys.length, target.keys.length); 84 | long start = System.currentTimeMillis(); 85 | long deadline = start + TimeUnit.SECONDS.toMillis(5); 86 | int i = 0; 87 | for (IntCursor c : source) { 88 | target.add(c.value); 89 | if ((i++ % 5000) == 0) { 90 | if (source.keys.length == target.keys.length) { 91 | System.out.println(String.format(Locale.ROOT, 92 | "Keys: %7d, %5d ms.: %s", 93 | i, 94 | System.currentTimeMillis() - start, 95 | debugging ? target.visualizeKeyDistribution(80) : "--")); 96 | } 97 | if (System.currentTimeMillis() >= deadline) { 98 | fail("Takes too long, something is wrong. Added " + i + " keys out of " + source.size()); 99 | } 100 | } 101 | } 102 | } 103 | 104 | /** */ 105 | @Test 106 | public void testHashSetClusteringAtFront2() 107 | { 108 | int keys = 100000; 109 | int expected = keys * 5; 110 | IntHashSet target = new IntHashSet(expected, 0.9) { 111 | @Override 112 | protected void allocateBuffers(int arraySize) { 113 | super.allocateBuffers(arraySize); 114 | System.out.println("[Rehashed to: " + arraySize + "]"); 115 | } 116 | }; 117 | 118 | long deadline = System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(15); 119 | IntHashSet source = new IntHashSet(expected, 0.9); 120 | int unique = 0; 121 | for (int i = 0; i < 200; i++) { 122 | source.clear(); 123 | while (source.size() < keys) { 124 | source.add(unique++); 125 | } 126 | 127 | long s = System.currentTimeMillis(); 128 | int firstSubsetOfKeys = 5000; 129 | for (IntCursor c : source) { 130 | target.add(c.value); 131 | if (firstSubsetOfKeys-- == 0) break; 132 | } 133 | long e = System.currentTimeMillis(); 134 | System.out.println(String.format(Locale.ROOT, 135 | "Keys: %7d, %5d ms. (%5d): %s", 136 | i, 137 | e - s, 138 | deadline - e, 139 | debugging ? target.visualizeKeyDistribution(80) : "--")); 140 | 141 | if (System.currentTimeMillis() > deadline) { 142 | fail("Takes too long, something is wrong. Added " + i + " batches."); 143 | } 144 | } 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /hppc/src/main/java/com/carrotsearch/hppc/HashOrderMixing.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc; 2 | 3 | import java.security.PrivilegedAction; 4 | import java.util.concurrent.Callable; 5 | import java.util.logging.Level; 6 | import java.util.logging.Logger; 7 | 8 | /** 9 | * Factory methods to acquire the most common types of 10 | * {@link HashOrderMixingStrategy}. 11 | * 12 | * @see HashOrderMixingStrategy 13 | */ 14 | public final class HashOrderMixing { 15 | public static final String PROPERTY_BIT_MIXER = "hppc.bitmixer"; 16 | 17 | private static Strategy strategy; 18 | 19 | public enum Strategy implements Callable { 20 | RANDOM { 21 | @Override 22 | public HashOrderMixingStrategy call() { 23 | return randomized(); 24 | } 25 | }, 26 | DETERMINISTIC { 27 | @Override 28 | public HashOrderMixingStrategy call() { 29 | return deterministic(); 30 | } 31 | }, 32 | NONE { 33 | @Override 34 | public HashOrderMixingStrategy call() { 35 | return none(); 36 | } 37 | }; 38 | } 39 | 40 | private HashOrderMixing() {} 41 | 42 | /** 43 | * @see #deterministic() 44 | */ 45 | private static final HashOrderMixingStrategy DETERMINISTIC = new HashOrderMixingStrategy() { 46 | @Override 47 | public int newKeyMixer(int newContainerBufferSize) { 48 | return BitMixer.mix32(newContainerBufferSize); 49 | } 50 | 51 | @Override 52 | public HashOrderMixingStrategy clone() { 53 | return this; 54 | } 55 | }; 56 | 57 | /** 58 | * Returns a randomized {@link HashOrderMixingStrategy} that issues unique 59 | * per-container seed. This minimizes the chances of hash distribution conflicts. 60 | */ 61 | public static HashOrderMixingStrategy randomized() { 62 | return RandomizedHashOrderMixer.INSTANCE; 63 | } 64 | 65 | /** 66 | * A constant {@link HashOrderMixingStrategy}. This is useful if one needs to have 67 | * deterministic key distribution but wishes to control it manually. 68 | * 69 | * Do not use the same constant for more than one container. 70 | * 71 | * Consider using {@linkplain ObjectScatterSet scatter maps or sets} instead 72 | * of constant hash order mixer. 73 | */ 74 | public static HashOrderMixingStrategy constant(final long seed) { 75 | return new HashOrderMixingStrategy() { 76 | @Override 77 | public int newKeyMixer(int newContainerBufferSize) { 78 | return (int) BitMixer.mix64(newContainerBufferSize ^ seed); 79 | } 80 | 81 | @Override 82 | public HashOrderMixingStrategy clone() { 83 | return this; 84 | } 85 | }; 86 | } 87 | 88 | /** 89 | * Deterministic {@link HashOrderMixingStrategy} will reorder keys depending 90 | * on the size of the container's buffer. 91 | * 92 | * This is inherently unsafe with hash containers using linear conflict 93 | * addressing. The only use case when this can be useful is to count/ collect 94 | * unique keys (for which scatter tables should be used). 95 | * 96 | * @deprecated Permanently deprecated as a warning signal. 97 | */ 98 | @Deprecated 99 | public static HashOrderMixingStrategy deterministic() { 100 | return DETERMINISTIC; 101 | } 102 | 103 | /** 104 | * This strategy does not change the hash order of keys at all. This 105 | * is inherently unsafe with hash containers using linear conflict 106 | * addressing. The only use case when this can be useful is to count/ collect 107 | * unique keys (for which scatter tables should be used). 108 | * 109 | * @deprecated Permanently deprecated as a warning signal. 110 | */ 111 | @Deprecated 112 | public static HashOrderMixingStrategy none() { 113 | return new HashOrderMixingStrategy() { 114 | @Override 115 | public int newKeyMixer(int newContainerBufferSize) { 116 | return 0; 117 | } 118 | 119 | @Override 120 | public HashOrderMixingStrategy clone() { 121 | return this; 122 | } 123 | }; 124 | } 125 | 126 | /** 127 | * Returns the currently configured default {@link HashOrderMixingStrategy}. 128 | */ 129 | public static HashOrderMixingStrategy defaultStrategy() { 130 | if (strategy == null) { 131 | try { 132 | String propValue = java.security.AccessController.doPrivileged(new PrivilegedAction() { 133 | @Override 134 | public String run() { 135 | return System.getProperty(PROPERTY_BIT_MIXER); 136 | } 137 | }); 138 | 139 | if (propValue != null) { 140 | for (Strategy s : Strategy.values()) { 141 | if (s.name().equalsIgnoreCase(propValue)) { 142 | strategy = s; 143 | break; 144 | } 145 | } 146 | } 147 | } catch (SecurityException e) { 148 | // If failed on security exception, don't panic. 149 | Logger.getLogger(Containers.class.getName()) 150 | .log(Level.INFO, "Failed to read 'tests.seed' property for initial random seed.", e); 151 | } 152 | 153 | if (strategy == null) { 154 | strategy = Strategy.RANDOM; 155 | } 156 | } 157 | 158 | try { 159 | return strategy.call(); 160 | } catch (Exception e) { 161 | throw new RuntimeException(e); // Effectively unreachable. 162 | } 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /hppc-template-processor/src/main/java/com/carrotsearch/hppc/Intrinsics.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc; 2 | 3 | import java.util.Objects; 4 | 5 | /** 6 | * Intrinsic methods that are fully functional for the source templates 7 | * (generic) and are replaced with low-level corresponding equivalents for the 8 | * generated primitive types. 9 | * 10 | * Whenever there is a generic type on a static method it can be used to parameterize 11 | * the given method based on the actual template type. Most intrinsics can guess their 12 | * generic template parameter (for example if the template has only one replaceable 13 | * type), but sometimes it may be necessary to provide the template type directly. 14 | * 15 | * This class should not appear in the final distribution (all methods are 16 | * replaced in templates. Use forbidden-apis checker to make sure this is the 17 | * case. 18 | */ 19 | public final class Intrinsics { 20 | /** 21 | * Anything that implements value-equality function as replaced by the 22 | * {@link #equals} intrinsic. 23 | * 24 | * Not a public interface because we want the implementing methods to be 25 | * effectively protected, but used for API consistency in templates. 26 | */ 27 | public interface EqualityFunction { 28 | boolean equals(Object v1, Object v2); 29 | } 30 | 31 | /** 32 | * Anything that distributes keys by their hash value. 33 | * 34 | * Not a public interface because we want the implementing methods to be 35 | * effectively protected, but used for API consistency in templates. * 36 | */ 37 | public interface KeyHasher { 38 | int hashKey(T key); 39 | } 40 | 41 | /** 42 | * Everything static. 43 | */ 44 | private Intrinsics() {} 45 | 46 | /** 47 | * Returns true if the provided value is an "empty key" marker. 48 | * For generic types the empty key is null, for any other type 49 | * it is an equivalent of zero. 50 | * 51 | * Testing for zeros should be compiled into fast machine code. 52 | */ 53 | public static boolean isEmpty(Object value) { 54 | return value == null; 55 | } 56 | 57 | /** 58 | * Returns the default "empty key" (null or 0 for 59 | * primitive types). 60 | */ 61 | public static T empty() { 62 | return (T) null; 63 | } 64 | 65 | /** 66 | * A template cast to the given type T. With type erasure it should work 67 | * internally just fine and it simplifies code. The cast will be erased for 68 | * primitive types. 69 | */ 70 | @SuppressWarnings("unchecked") 71 | public static T cast(Object value) { 72 | return (T) value; 73 | } 74 | 75 | /** 76 | * Creates an array for the given template type. 77 | */ 78 | @SuppressWarnings("unchecked") 79 | public static T[] newArray(int arraySize) { 80 | return (T[]) new Object[arraySize]; 81 | } 82 | 83 | /** 84 | * Compare two keys for equivalence. 85 | * 86 | * Generic types are compared using the delegate function. 87 | * 88 | * Primitive types are compared using ==, except for 89 | * floating-point types where they're compared by their actual representation 90 | * bits as returned from {@link Double#doubleToLongBits(double)} and 91 | * {@link Float#floatToIntBits(float)}. 92 | */ 93 | public static boolean equals(EqualityFunction delegate, Object e1, Object e2) { 94 | return delegate.equals(e1, e2); 95 | } 96 | 97 | /** 98 | * Compare two keys for equivalence. 99 | * 100 | * Generic types are compared for null-equivalence or using 101 | * {@link Object#equals(Object)}. 102 | * 103 | * Primitive types are compared using ==, except for 104 | * floating-point types where they're compared by their actual representation 105 | * bits as returned from {@link Double#doubleToLongBits(double)} and 106 | * {@link Float#floatToIntBits(float)}. 107 | */ 108 | public static boolean equals(Object e1, Object e2) { 109 | return Objects.equals(e1, e2); 110 | } 111 | 112 | /** 113 | * An intrinsic that is replaced with plain addition of arguments for 114 | * primitive template types. Invalid for non-number generic types. 115 | */ 116 | @SuppressWarnings("unchecked") 117 | public static T add(T op1, T op2) { 118 | if (op1.getClass() != op2.getClass()) { 119 | throw new RuntimeException("Arguments of different classes: " + op1 + " " + op2); 120 | } 121 | 122 | if (Byte.class.isInstance(op1)) { 123 | return (T)(Byte)(byte)(((Byte) op1).byteValue() + ((Byte) op2).byteValue()); 124 | } 125 | if (Short.class.isInstance(op1)) { 126 | return (T)(Short)(short)(((Short) op1).shortValue() + ((Short) op2).shortValue()); 127 | } 128 | if (Character.class.isInstance(op1)) { 129 | return (T)(Character)(char)(((Character) op1).charValue() + ((Character) op2).charValue()); 130 | } 131 | if (Integer.class.isInstance(op1)) { 132 | return (T)(Integer)(((Integer) op1).intValue() + ((Integer) op2).intValue()); 133 | } 134 | if (Float.class.isInstance(op1)) { 135 | return (T)(Float)(((Float) op1).floatValue() + ((Float) op2).floatValue()); 136 | } 137 | if (Long.class.isInstance(op1)) { 138 | return (T)(Long)(((Long) op1).longValue() + ((Long) op2).longValue()); 139 | } 140 | if (Double.class.isInstance(op1)) { 141 | return (T)(Double)(((Double) op1).doubleValue() + ((Double) op2).doubleValue()); 142 | } 143 | 144 | throw new UnsupportedOperationException("Invalid for arbitrary types: " + op1 + " " + op2); 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /hppc/src/main/templates/com/carrotsearch/hppc/KTypeStack.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc; 2 | 3 | /* #if ($TemplateOptions.KTypeGeneric) */ 4 | import java.util.Arrays; 5 | /* #end */ 6 | 7 | import com.carrotsearch.hppc.cursors.KTypeCursor; 8 | 9 | /** 10 | * A subclass of {@link KTypeArrayList} adding stack-related utility methods. 11 | * The top of the stack is at the {@link #size()} - 1 element. 12 | */ 13 | /*! #if ($TemplateOptions.KTypeGeneric) @SuppressWarnings("unchecked") #end !*/ 14 | /*! ${TemplateOptions.generatedAnnotation} !*/ 15 | public class KTypeStack extends KTypeArrayList { 16 | /** 17 | * New instance with sane defaults. 18 | */ 19 | public KTypeStack() { 20 | super(); 21 | } 22 | 23 | /** 24 | * New instance with sane defaults. 25 | * 26 | * @param expectedElements 27 | * The expected number of elements guaranteed not to cause buffer 28 | * expansion (inclusive). 29 | */ 30 | public KTypeStack(int expectedElements) { 31 | super(expectedElements); 32 | } 33 | 34 | /** 35 | * New instance with sane defaults. 36 | * 37 | * @param expectedElements 38 | * The expected number of elements guaranteed not to cause buffer 39 | * expansion (inclusive). 40 | * @param resizer 41 | * Underlying buffer sizing strategy. 42 | */ 43 | public KTypeStack(int expectedElements, ArraySizingStrategy resizer) { 44 | super(expectedElements, resizer); 45 | } 46 | 47 | /** 48 | * Create a stack by pushing all elements of another container to it. 49 | */ 50 | public KTypeStack(KTypeContainer container) { 51 | super(container); 52 | } 53 | 54 | /** 55 | * Adds one KType to the stack. 56 | */ 57 | public void push(KType e1) { 58 | ensureBufferSpace(1); 59 | buffer[elementsCount++] = e1; 60 | } 61 | 62 | /** 63 | * Adds two KTypes to the stack. 64 | */ 65 | public void push(KType e1, KType e2) { 66 | ensureBufferSpace(2); 67 | buffer[elementsCount++] = e1; 68 | buffer[elementsCount++] = e2; 69 | } 70 | 71 | /** 72 | * Adds three KTypes to the stack. 73 | */ 74 | public void push(KType e1, KType e2, KType e3) { 75 | ensureBufferSpace(3); 76 | buffer[elementsCount++] = e1; 77 | buffer[elementsCount++] = e2; 78 | buffer[elementsCount++] = e3; 79 | } 80 | 81 | /** 82 | * Adds four KTypes to the stack. 83 | */ 84 | public void push(KType e1, KType e2, KType e3, KType e4) { 85 | ensureBufferSpace(4); 86 | buffer[elementsCount++] = e1; 87 | buffer[elementsCount++] = e2; 88 | buffer[elementsCount++] = e3; 89 | buffer[elementsCount++] = e4; 90 | } 91 | 92 | /** 93 | * Add a range of array elements to the stack. 94 | */ 95 | public void push(KType[] elements, int start, int len) { 96 | assert start >= 0 && len >= 0; 97 | 98 | ensureBufferSpace(len); 99 | System.arraycopy(elements, start, buffer, elementsCount, len); 100 | elementsCount += len; 101 | } 102 | 103 | /** 104 | * Vararg-signature method for pushing elements at the top of the stack. 105 | *

106 | * This method is handy, but costly if used in tight loops (anonymous array 107 | * passing) 108 | *

109 | */ 110 | /* #if ($TemplateOptions.KTypeGeneric) */ 111 | @SafeVarargs 112 | /* #end */ 113 | public final void push(KType... elements) { 114 | push(elements, 0, elements.length); 115 | } 116 | 117 | /** 118 | * Pushes all elements from another container to the top of the stack. 119 | */ 120 | public int pushAll(KTypeContainer container) { 121 | return addAll(container); 122 | } 123 | 124 | /** 125 | * Pushes all elements from another iterable to the top of the stack. 126 | */ 127 | public int pushAll(Iterable> iterable) { 128 | return addAll(iterable); 129 | } 130 | 131 | /** 132 | * Discard an arbitrary number of elements from the top of the stack. 133 | */ 134 | public void discard(int count) { 135 | assert elementsCount >= count; 136 | 137 | elementsCount -= count; 138 | /* #if ($TemplateOptions.KTypeGeneric) */ 139 | Arrays.fill(buffer, elementsCount, elementsCount + count, null); 140 | /* #end */ 141 | } 142 | 143 | /** 144 | * Discard the top element from the stack. 145 | */ 146 | public void discard() { 147 | assert elementsCount > 0; 148 | 149 | elementsCount--; 150 | /* #if ($TemplateOptions.KTypeGeneric) */ 151 | buffer[elementsCount] = null; 152 | /* #end */ 153 | } 154 | 155 | /** 156 | * Remove the top element from the stack and return it. 157 | */ 158 | public KType pop() { 159 | assert elementsCount > 0; 160 | 161 | final KType v = Intrinsics. cast(buffer[--elementsCount]); 162 | /* #if ($TemplateOptions.KTypeGeneric) */ 163 | buffer[elementsCount] = null; 164 | /* #end */ 165 | return v; 166 | } 167 | 168 | /** 169 | * Peek at the top element on the stack. 170 | */ 171 | public KType peek() { 172 | assert elementsCount > 0; 173 | return Intrinsics. cast(buffer[elementsCount - 1]); 174 | } 175 | 176 | /** 177 | * Create a stack by pushing a variable number of arguments to it. 178 | */ 179 | /* #if ($TemplateOptions.KTypeGeneric) */ 180 | @SafeVarargs 181 | /* #end */ 182 | public static KTypeStack from(KType... elements) { 183 | final KTypeStack stack = new KTypeStack(elements.length); 184 | stack.push(elements); 185 | return stack; 186 | } 187 | 188 | /** 189 | * {@inheritDoc} 190 | */ 191 | @Override 192 | public KTypeStack clone() { 193 | return (KTypeStack) super.clone(); 194 | } 195 | } 196 | -------------------------------------------------------------------------------- /hppc/src/main/java/com/carrotsearch/hppc/BitSetIterator.java: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Repackaged from org.apache.lucene.util.OpenBitSet (Lucene). 4 | * svn rev. 893130, http://svn.apache.org/repos/asf/lucene/java/trunk/ 5 | * 6 | * Minor changes in class hierarchy, removed serialization. 7 | */ 8 | 9 | /** 10 | * Licensed to the Apache Software Foundation (ASF) under one or more 11 | * contributor license agreements. See the NOTICE file distributed with 12 | * this work for additional information regarding copyright ownership. 13 | * The ASF licenses this file to You under the Apache License, Version 2.0 14 | * (the "License"); you may not use this file except in compliance with 15 | * the License. You may obtain a copy of the License at 16 | * 17 | * http://www.apache.org/licenses/LICENSE-2.0 18 | * 19 | * Unless required by applicable law or agreed to in writing, software 20 | * distributed under the License is distributed on an "AS IS" BASIS, 21 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 22 | * See the License for the specific language governing permissions and 23 | * limitations under the License. 24 | */ 25 | 26 | package com.carrotsearch.hppc; 27 | 28 | /** 29 | * An iterator to iterate over set bits in an BitSet. This is faster than nextSetBit() for 30 | * iterating over the complete set of bits, especially when the density of the bits set is 31 | * high. 32 | */ 33 | public class BitSetIterator { 34 | // The General Idea: instead of having an array per byte that has 35 | // the offsets of the next set bit, that array could be 36 | // packed inside a 32 bit integer (8 4 bit numbers). That 37 | // should be faster than accessing an array for each index, and 38 | // the total array size is kept smaller (256*sizeof(int))=1K 39 | final static int[] bitlist={ 40 | 0x0, 0x1, 0x2, 0x21, 0x3, 0x31, 0x32, 0x321, 0x4, 0x41, 0x42, 0x421, 0x43, 41 | 0x431, 0x432, 0x4321, 0x5, 0x51, 0x52, 0x521, 0x53, 0x531, 0x532, 0x5321, 42 | 0x54, 0x541, 0x542, 0x5421, 0x543, 0x5431, 0x5432, 0x54321, 0x6, 0x61, 0x62, 43 | 0x621, 0x63, 0x631, 0x632, 0x6321, 0x64, 0x641, 0x642, 0x6421, 0x643, 44 | 0x6431, 0x6432, 0x64321, 0x65, 0x651, 0x652, 0x6521, 0x653, 0x6531, 0x6532, 45 | 0x65321, 0x654, 0x6541, 0x6542, 0x65421, 0x6543, 0x65431, 0x65432, 0x654321, 46 | 0x7, 0x71, 0x72, 0x721, 0x73, 0x731, 0x732, 0x7321, 0x74, 0x741, 0x742, 47 | 0x7421, 0x743, 0x7431, 0x7432, 0x74321, 0x75, 0x751, 0x752, 0x7521, 0x753, 48 | 0x7531, 0x7532, 0x75321, 0x754, 0x7541, 0x7542, 0x75421, 0x7543, 0x75431, 49 | 0x75432, 0x754321, 0x76, 0x761, 0x762, 0x7621, 0x763, 0x7631, 0x7632, 50 | 0x76321, 0x764, 0x7641, 0x7642, 0x76421, 0x7643, 0x76431, 0x76432, 0x764321, 51 | 0x765, 0x7651, 0x7652, 0x76521, 0x7653, 0x76531, 0x76532, 0x765321, 0x7654, 52 | 0x76541, 0x76542, 0x765421, 0x76543, 0x765431, 0x765432, 0x7654321, 0x8, 53 | 0x81, 0x82, 0x821, 0x83, 0x831, 0x832, 0x8321, 0x84, 0x841, 0x842, 0x8421, 54 | 0x843, 0x8431, 0x8432, 0x84321, 0x85, 0x851, 0x852, 0x8521, 0x853, 0x8531, 55 | 0x8532, 0x85321, 0x854, 0x8541, 0x8542, 0x85421, 0x8543, 0x85431, 0x85432, 56 | 0x854321, 0x86, 0x861, 0x862, 0x8621, 0x863, 0x8631, 0x8632, 0x86321, 0x864, 57 | 0x8641, 0x8642, 0x86421, 0x8643, 0x86431, 0x86432, 0x864321, 0x865, 0x8651, 58 | 0x8652, 0x86521, 0x8653, 0x86531, 0x86532, 0x865321, 0x8654, 0x86541, 59 | 0x86542, 0x865421, 0x86543, 0x865431, 0x865432, 0x8654321, 0x87, 0x871, 60 | 0x872, 0x8721, 0x873, 0x8731, 0x8732, 0x87321, 0x874, 0x8741, 0x8742, 61 | 0x87421, 0x8743, 0x87431, 0x87432, 0x874321, 0x875, 0x8751, 0x8752, 0x87521, 62 | 0x8753, 0x87531, 0x87532, 0x875321, 0x8754, 0x87541, 0x87542, 0x875421, 63 | 0x87543, 0x875431, 0x875432, 0x8754321, 0x876, 0x8761, 0x8762, 0x87621, 64 | 0x8763, 0x87631, 0x87632, 0x876321, 0x8764, 0x87641, 0x87642, 0x876421, 65 | 0x87643, 0x876431, 0x876432, 0x8764321, 0x8765, 0x87651, 0x87652, 0x876521, 66 | 0x87653, 0x876531, 0x876532, 0x8765321, 0x87654, 0x876541, 0x876542, 67 | 0x8765421, 0x876543, 0x8765431, 0x8765432, 0x87654321 68 | }; 69 | 70 | /***** the python code that generated bitlist 71 | def bits2int(val): 72 | arr=0 73 | for shift in range(8,0,-1): 74 | if val & 0x80: 75 | arr = (arr << 4) | shift 76 | val = val << 1 77 | return arr 78 | 79 | def int_table(): 80 | tbl = [ hex(bits2int(val)).strip('L') for val in range(256) ] 81 | return ','.join(tbl) 82 | ******/ 83 | 84 | // hmmm, what about an iterator that finds zeros though, 85 | // or a reverse iterator... should they be separate classes 86 | // for efficiency, or have a common root interface? (or 87 | // maybe both? could ask for a SetBitsIterator, etc... 88 | 89 | private final long[] arr; 90 | private final int words; 91 | private int i=-1; 92 | private long word; 93 | private int wordShift; 94 | private int indexArray; 95 | 96 | public BitSetIterator(BitSet obs) { 97 | this(obs.bits, obs.wlen); 98 | } 99 | 100 | public BitSetIterator(long[] bits, int numWords) { 101 | arr = bits; 102 | words = numWords; 103 | } 104 | 105 | // 64 bit shifts 106 | private void shift() { 107 | if ((int)word ==0) {wordShift +=32; word = word >>>32; } 108 | if ((word & 0x0000FFFF) == 0) { wordShift +=16; word >>>=16; } 109 | if ((word & 0x000000FF) == 0) { wordShift +=8; word >>>=8; } 110 | indexArray = bitlist[(int)word & 0xff]; 111 | } 112 | 113 | public final static int NO_MORE = -1; 114 | 115 | public int nextSetBit() { 116 | if (indexArray == 0) { 117 | if (word != 0) { 118 | word >>>= 8; 119 | wordShift += 8; 120 | } 121 | 122 | while (word == 0) { 123 | if (++i >= words) { 124 | return NO_MORE; 125 | } 126 | word = arr[i]; 127 | wordShift = -1; // loop invariant code motion should move this 128 | } 129 | 130 | // after the first time, should I go with a linear search, or 131 | // stick with the binary search in shift? 132 | shift(); 133 | } 134 | 135 | int bitIndex = (indexArray & 0x0f) + wordShift; 136 | indexArray >>>= 4; 137 | // should i<<6 be cached as a separate variable? 138 | // it would only save one cycle in the best circumstances. 139 | return (i<<6) + bitIndex; 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /hppc/src/test/templates/com/carrotsearch/hppc/KTypeStackTest.java: -------------------------------------------------------------------------------- 1 | package com.carrotsearch.hppc; 2 | 3 | import static com.carrotsearch.hppc.TestUtils.*; 4 | 5 | import org.assertj.core.api.Assertions; 6 | import org.junit.*; 7 | 8 | /** 9 | * Unit tests for {@link KTypeStack}. 10 | */ 11 | /*! ${TemplateOptions.generatedAnnotation} !*/ 12 | public class KTypeStackTest extends AbstractKTypeTest 13 | { 14 | /** 15 | * Per-test fresh initialized instance. 16 | */ 17 | public KTypeStack stack; 18 | 19 | /* */ 20 | @Before 21 | public void initialize() 22 | { 23 | stack = new KTypeStack<>(); 24 | } 25 | 26 | /* */ 27 | @Test 28 | public void testInitiallyEmpty() 29 | { 30 | assertEquals(0, stack.size()); 31 | } 32 | 33 | /* */ 34 | @Test 35 | public void testPush1() 36 | { 37 | stack.push(key1); 38 | assertEquals(1, stack.size()); 39 | assertEquals2(key1, stack.peek()); 40 | assertEquals2(key1, stack.pop()); 41 | assertEquals(0, stack.size()); 42 | } 43 | 44 | /* */ 45 | @Test 46 | public void testPush2() 47 | { 48 | stack.push(key1, key3); 49 | assertEquals(2, stack.size()); 50 | assertEquals2(key3, stack.peek()); 51 | assertEquals2(key1, stack.get(0)); 52 | assertEquals2(key3, stack.get(1)); 53 | assertEquals2(key3, stack.pop()); 54 | assertEquals2(key1, stack.pop()); 55 | assertEquals(0, stack.size()); 56 | } 57 | 58 | /* */ 59 | @Test 60 | public void testPushArray() 61 | { 62 | stack.push(asArray(1, 2, 3, 4), 1, 2); 63 | assertEquals(2, stack.size()); 64 | assertEquals2(key2, stack.get(0)); 65 | assertEquals2(key3, stack.get(1)); 66 | } 67 | 68 | /* */ 69 | @Test 70 | public void testAddAllPushAll() 71 | { 72 | KTypeArrayList list2 = new KTypeArrayList<>(); 73 | list2.add(asArray(0, 1, 2)); 74 | 75 | stack.addAll(list2); 76 | stack.pushAll(list2); 77 | 78 | assertListEquals(stack.toArray(), 0, 1, 2, 0, 1, 2); 79 | } 80 | 81 | /*! #if ($TemplateOptions.KTypeGeneric) !*/ 82 | /* */ 83 | @Test 84 | public void testNullify() 85 | { 86 | stack.push(asArray(1, 2, 3, 4)); 87 | stack.pop(); 88 | stack.discard(); 89 | stack.discard(2); 90 | assertEquals(0, stack.size()); 91 | 92 | /* 93 | * Cleanup only for the generic version (to allow GCing of references). 94 | */ 95 | for (int i = 0; i < stack.buffer.length; i++) 96 | { 97 | assertEquals2(Intrinsics. empty(), stack.buffer[i]); 98 | } 99 | } 100 | /*! #end !*/ 101 | 102 | /* */ 103 | @Test 104 | public void testDiscard() 105 | { 106 | stack.push(key1, key3); 107 | assertEquals(2, stack.size()); 108 | 109 | stack.discard(); 110 | assertEquals(1, stack.size()); 111 | 112 | stack.push(key4); 113 | assertEquals(2, stack.size()); 114 | 115 | assertEquals2(1, stack.get(0)); 116 | assertEquals2(4, stack.get(1)); 117 | 118 | stack.discard(2); 119 | assertEquals(0, stack.size()); 120 | } 121 | 122 | /* */ 123 | @Test(expected = AssertionError.class) 124 | public void testGetAssertions() 125 | { 126 | stack.push(key1); 127 | stack.pop(); 128 | stack.get(0); 129 | } 130 | 131 | /* */ 132 | @Test(expected = AssertionError.class) 133 | public void testDiscardAssertions() 134 | { 135 | stack.push(key1); 136 | stack.discard(2); 137 | } 138 | 139 | /* */ 140 | @Test 141 | public void testHashCodeEquals() 142 | { 143 | KTypeStack s0 = new KTypeStack<>(); 144 | assertEquals(1, s0.hashCode()); 145 | 146 | KTypeStack s1 = KTypeStack.from(key1, key2, key3); 147 | KTypeStack s2 = KTypeStack.from(key1, key2, key3); 148 | 149 | assertEquals(s1.hashCode(), s2.hashCode()); 150 | assertEquals(s1, s2); 151 | 152 | s1 = KTypeStack.from(key1, key2); 153 | assertFalse(s1.equals(s2)); 154 | } 155 | 156 | /* */ 157 | @Test 158 | public void testHashCodeEqualsWithOtherContainer() 159 | { 160 | KTypeStack s1 = KTypeStack.from(key1, key2, key3); 161 | KTypeArrayList s2 = KTypeArrayList.from(key1, key2, key3); 162 | 163 | assertEquals(s1.hashCode(), s2.hashCode()); 164 | assertTrue(s1.equalElements(s2)); 165 | } 166 | 167 | /*! #if ($TemplateOptions.KTypeGeneric) !*/ 168 | @Test 169 | public void testToArrayWithClass() 170 | { 171 | KTypeStack l1 = KTypeStack.from(1, 2, 3); 172 | Integer[] result = l1.toArray(Integer.class); 173 | assertArrayEquals(new Integer [] {1, 2, 3}, result); // dummy 174 | } 175 | /*! #end !*/ 176 | 177 | /*! #if ($TemplateOptions.KTypeGeneric) !*/ 178 | @Test 179 | public void testToArray() 180 | { 181 | KTypeStack l1 = KTypeStack.from(1, 2, 3); 182 | Object[] result = l1.toArray(); 183 | assertArrayEquals(new Object [] {1, 2, 3}, result); // dummy 184 | } 185 | /*! #end !*/ 186 | 187 | /* */ 188 | @Test 189 | public void testClone() 190 | { 191 | stack.push(key1, key2, key3); 192 | 193 | KTypeStack cloned = stack.clone(); 194 | cloned.removeAll(key1); 195 | 196 | assertSortedListEquals(stack.toArray(), key1, key2, key3); 197 | assertSortedListEquals(cloned.toArray(), key2, key3); 198 | } 199 | 200 | /* */ 201 | @Test 202 | public void testToString() 203 | { 204 | assertEquals("[" 205 | + key1 + ", " 206 | + key2 + ", " 207 | + key3 + "]", KTypeStack.from(key1, key2, key3).toString()); 208 | } 209 | 210 | /* */ 211 | @Test 212 | public void testEqualsSameClass() 213 | { 214 | KTypeStack l1 = KTypeStack.from(k1, k2, k3); 215 | KTypeStack l2 = KTypeStack.from(k1, k2, k3); 216 | KTypeStack l3 = KTypeStack.from(k1, k3, k2); 217 | 218 | Assertions.assertThat(l1).isEqualTo(l2); 219 | Assertions.assertThat(l1.hashCode()).isEqualTo(l2.hashCode()); 220 | Assertions.assertThat(l1).isNotEqualTo(l3); 221 | } 222 | 223 | /* */ 224 | @Test 225 | public void testEqualsSubClass() 226 | { 227 | class Sub extends KTypeStack { 228 | }; 229 | 230 | KTypeStack l1 = KTypeStack.from(k1, k2, k3); 231 | KTypeStack l2 = new Sub(); 232 | KTypeStack l3 = new Sub(); 233 | l2.addAll(l1); 234 | l3.addAll(l1); 235 | 236 | Assertions.assertThat(l2).isEqualTo(l3); 237 | Assertions.assertThat(l1).isNotEqualTo(l2); 238 | 239 | KTypeArrayList l4 = new KTypeArrayList<>(); 240 | l4.addAll(l1); 241 | Assertions.assertThat(l1).isNotEqualTo(l4); 242 | Assertions.assertThat(l1.equalElements(l4)).isTrue(); 243 | } 244 | } 245 | --------------------------------------------------------------------------------