diff --git a/CREDITS b/CREDITS index e2987d11..7114371a 100644 --- a/CREDITS +++ b/CREDITS @@ -6,21 +6,20 @@ - Creator of Eaglercraft - Ported the Minecraft 1.8 src to TeaVM - - Wrote HW accelerated OpenGL 1.3 emulator - - Wrote the default shader pack + - Optimized the Minecraft 1.8 src + - Made the platform abstraction layer + - Made HW accelerated OpenGL 1.3 emulator + - Made the default shader pack - Made the integrated PBR resource pack - Added touch and mobile device support - - Wrote all desktop emulation code - - Wrote EaglercraftXBungee - - Wrote EaglercraftXVelocity - - Wrote WebRTC relay server - - Wrote voice chat server - - Wrote the patch and build system + - Made the multiplayer backends + - Made the shared world relay server + - Made the patch and build system ayunami2000: - Many bug fixes - - WebRTC LAN worlds + - WebRTC shared worlds - WebRTC voice chat - Worked on touch support - Made velocity plugin work @@ -29,6 +28,11 @@ - Added seamless fullscreen - Created the replit + cire3: + + - Created the Gradle plugin + - Proponent of Kotlin DSL + Code used within EaglercraftX diff --git a/README.md b/README.md index f63e92f5..00e3e530 100644 --- a/README.md +++ b/README.md @@ -48,9 +48,9 @@ The JavaScript runtime of EaglercraftX 1.8 is currently known to work on browser ## WebAssembly GC Support -EaglercraftX 1.8 also has an experimental WebAssembly GC (WASM-GC) runtime, almost all of the features supported on the JavaScript runtime are also supported on the WebAssembly GC runtime, however it is still incompatible with several major browsers (especially Safari) and will not run in Chrome unless you can access the `chrome://flags` menu or request an origin trial token from Google for your website. Its based on experimental technology and may still crash sometimes due to browser bugs or unresolved issues in the Java to WASM compiler. Hopefully in the coming months the required feature (JSPI, WebAssembly JavaScript Promise Integration) will become enabled by default on the Chrome browser. It performs significantly better than the JavaScript client, around 50% more FPS and TPS in some cases, and will hopefully replace it someday. Just make sure you enable VSync when you play it, otherwise the game will run "too fast" and choke the browser's event loop, causing input lag. +EaglercraftX 1.8 also has an experimental WebAssembly GC (WASM-GC) runtime, almost all of the features supported on the JavaScript runtime are also supported on the WebAssembly GC runtime, however it is still incompatible with several major browsers (especially Safari) and will not run in Chrome unless you can access the `chrome://flags` menu or request an origin trial token from Google for your website. Its based on experimental technology and may still crash sometimes, mostly due to browser bugs. Hopefully in the coming months the required feature (JSPI, WebAssembly JavaScript Promise Integration) will become enabled by default on the Chrome browser. It performs significantly better than the JavaScript client, around 50% more FPS and TPS in some cases, and will hopefully replace it someday. Just make sure you enable VSync when you play it, otherwise the game will run "too fast" and choke the browser's event loop, causing input lag. -You can compile the WebAssembly GC runtime by creating a development environment (workspace) and reading the README in the "wasm_gc_teavm" folder. +There is no GUI for compiling the WASM-GC client at the moment, you need to compile it using the `MakeWASMClientBundle` script in the development environment. ## Singleplayer @@ -208,5 +208,3 @@ The `crashReportShow` hook can be used to capture crash reports and append addit ## Developing a Client There is currently no system in place to make forks of 1.8 and merge commits made to the patch files in this repository with the patch files or workspace of the fork, you're on your own if you try to keep a fork of this repo for reasons other than to contribute to it - -**Note:** If you are trying to use the desktop runtime on Linux, make sure you add the "desktopRuntime" folder to the `LD_LIBRARY_PATH` environment variable of the Java process. This should be done automatically by the Eclipse project's default run configuration, but it might not work properly on every system, or when the Eclipse project is imported into IntelliJ. diff --git a/buildtools/BuildTools.jar b/buildtools/BuildTools.jar index 9c5a3b59..697b34e6 100644 Binary files a/buildtools/BuildTools.jar and b/buildtools/BuildTools.jar differ diff --git a/buildtools/Java17Check.jar b/buildtools/Java17Check.jar new file mode 100644 index 00000000..9485aa7d Binary files /dev/null and b/buildtools/Java17Check.jar differ diff --git a/buildtools/src/main/java/net/lax1dude/eaglercraft/v1_8/buildtools/gui/CompileLatestClientFrame.java b/buildtools/src/main/java/net/lax1dude/eaglercraft/v1_8/buildtools/gui/CompileLatestClientFrame.java index 747ab74a..b1a61a5e 100644 --- a/buildtools/src/main/java/net/lax1dude/eaglercraft/v1_8/buildtools/gui/CompileLatestClientFrame.java +++ b/buildtools/src/main/java/net/lax1dude/eaglercraft/v1_8/buildtools/gui/CompileLatestClientFrame.java @@ -471,7 +471,7 @@ public class CompileLatestClientFrame { txtpnfuckOffwelcome.setEditable(false); txtpnfuckOffwelcome.setMargin(new Insets(10, 10, 10, 10)); txtpnfuckOffwelcome.setContentType("text/html"); - txtpnfuckOffwelcome.setText("\r\n
Welcome to the EaglercraftX 1.8 Client Compiler
\r\nThis tool will allow you to automatically compile the latest version of the EaglercraftX 1.8 client using the files in this repository.
\r\nYou are required to download several required files manually in order to better respect the Microsoft/Mojang TOS. The links to these files will be provided.
\r\nTo view or modify portions of the EaglercraftX 1.8 source code directly, please use the other batch files to generate a gradle project instead of compiling the javascript files directly
\r\nIf you are from Microsoft/Mojang or the developer of MCP trying to get dirt on me, please just let me live my life, the repository does not contain your intellectual property. Using this code to play your game for free is not the default behavior of the gateway plugin or this compiler utility and is not encouraged by the documentation
\r\n\r\n"); + txtpnfuckOffwelcome.setText("\r\nWelcome to the EaglercraftX 1.8 Client Compiler
\r\nThis tool will allow you to automatically compile the latest version of the EaglercraftX 1.8 client using the files in this repository.
\r\nYou are required to download several required files manually in order to better respect the Microsoft/Mojang TOS. The links to these files will be provided.
\r\nTo view or modify portions of the EaglercraftX 1.8 source code directly, please use the other batch files to generate a gradle project instead of compiling the javascript files directly
\r\nThis tool will only build the JavaScript client, to build WASM-GC please create a workspace and use the Gradle project to build it instead.
\r\n\r\n"); pageHome.add(txtpnfuckOffwelcome, BorderLayout.CENTER); JPanel pageLicense = new JPanel(); diff --git a/buildtools/src/main/java/net/lax1dude/eaglercraft/v1_8/buildtools/gui/CompileLatestClientGUI.java b/buildtools/src/main/java/net/lax1dude/eaglercraft/v1_8/buildtools/gui/CompileLatestClientGUI.java index b5693694..110426fa 100644 --- a/buildtools/src/main/java/net/lax1dude/eaglercraft/v1_8/buildtools/gui/CompileLatestClientGUI.java +++ b/buildtools/src/main/java/net/lax1dude/eaglercraft/v1_8/buildtools/gui/CompileLatestClientGUI.java @@ -66,16 +66,16 @@ public class CompileLatestClientGUI { | UnsupportedLookAndFeelException e) { System.err.println("Could not set system look and feel: " + e.toString()); } - if(!System.getProperty("eaglercraft.isJava11", "false").equalsIgnoreCase("true")) { + if(!System.getProperty("eaglercraft.isJava17", "false").equalsIgnoreCase("true")) { try { if (!(boolean) Class - .forName("net.lax1dude.eaglercraft.v1_8.buildtools.Java11Check", true, - new URLClassLoader(new URL[] { (new File("buildtools/Java11Check.jar")).toURI().toURL() })) + .forName("net.lax1dude.eaglercraft.v1_8.buildtools.Java17Check", true, + new URLClassLoader(new URL[] { (new File("buildtools/Java17Check.jar")).toURI().toURL() })) .getMethod("classLoadCheck").invoke(null)) { throw new RuntimeException("wtf?"); } }catch(Throwable t) { - JOptionPane.showMessageDialog(null, "Error: Java 11 is required to run this program", "Unsupported JRE", JOptionPane.ERROR_MESSAGE); + JOptionPane.showMessageDialog(null, "Error: Java 17 is required to run this program", "Unsupported JRE", JOptionPane.ERROR_MESSAGE); System.exit(-1); return; } @@ -90,7 +90,7 @@ public class CompileLatestClientGUI { System.setErr(new PrintStream(new ConsoleRedirector(true))); if(JavaC.jdkHome == null) { if(JOptionPane.showConfirmDialog(frame.frmCompileLatestClient, "Error: A JDK is required to run this program!\nYou are currently running on a JRE\nDo you have a JDK installed that you would like to use instead?", "Unsupported JRE", JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) { - JOptionPane.showMessageDialog(frame.frmCompileLatestClient, "You need at least JDK 8 to compile EaglercraftX 1.8!\nSelect the path to the installation you want to use", "Unsupported JRE", JOptionPane.INFORMATION_MESSAGE); + JOptionPane.showMessageDialog(frame.frmCompileLatestClient, "You need at least JDK 17 to compile EaglercraftX 1.8!\nSelect the path to the installation you want to use", "Unsupported JRE", JOptionPane.INFORMATION_MESSAGE); JFileChooser fileChooser = new JFileChooser((new File(System.getProperty("java.home"))).getParentFile()); fileChooser.setMultiSelectionEnabled(false); fileChooser.setFileHidingEnabled(false); @@ -106,7 +106,7 @@ public class CompileLatestClientGUI { } } } - JOptionPane.showMessageDialog(frame.frmCompileLatestClient, "Please install JDK 8 or newer to continue", "Unsupported JRE", JOptionPane.ERROR_MESSAGE); + JOptionPane.showMessageDialog(frame.frmCompileLatestClient, "Please install JDK 17 or newer to continue", "Unsupported JRE", JOptionPane.ERROR_MESSAGE); System.exit(-1); return; } @@ -256,6 +256,7 @@ public class CompileLatestClientGUI { new File(repositoryFolder, "sources/protocol-game/java"), new File(repositoryFolder, "sources/protocol-relay/java"), new File(repositoryFolder, "sources/teavm/java"), + new File(repositoryFolder, "sources/teavm/resources"), new File(repositoryFolder, "sources/teavm-boot-menu/java")); }catch(IOException ex) { throw new CompileFailureException("failed to run javac compiler! " + ex.toString(), ex); @@ -331,11 +332,11 @@ public class CompileLatestClientGUI { File classesJS = new File(outputDirectory, "classes.js"); - if(!ES6Compat.patchClassesJS(classesJS, new File(repositoryFolder, "sources/setup/workspace_template/javascript/ES6ShimScript.txt"))) { + if(!ES6Compat.patchClassesJS(classesJS, new File(repositoryFolder, "sources/setup/workspace_template/target_teavm_javascript/javascript/ES6ShimScript.txt"))) { System.err.println("Error: could not inject shim, continuing anyway because it is not required"); } - File epkCompiler = new File(repositoryFolder, "sources/setup/workspace_template/desktopRuntime/CompileEPK.jar"); + File epkCompiler = new File(repositoryFolder, "sources/setup/workspace_template/target_teavm_javascript/buildtools/CompileEPK.jar"); if(!epkCompiler.exists()) { throw new CompileFailureException("EPKCompiler JAR file is missing: " + epkCompiler.getAbsolutePath()); @@ -390,9 +391,9 @@ public class CompileLatestClientGUI { if(generateOfflineDownload) { System.out.println("Running offline download generator..."); System.out.println(); - File offlineDownloadGenerator = new File(repositoryFolder, "sources/setup/workspace_template/desktopRuntime/MakeOfflineDownload.jar"); + File offlineDownloadGenerator = new File(repositoryFolder, "sources/setup/workspace_template/target_teavm_javascript/buildtools/MakeOfflineDownload.jar"); MakeOfflineDownload.compilerMain(offlineDownloadGenerator, new String[] { - (new File(repositoryFolder, "sources/setup/workspace_template/javascript/OfflineDownloadTemplate.txt")).getAbsolutePath(), + (new File(repositoryFolder, "sources/setup/workspace_template/target_teavm_javascript/javascript/OfflineDownloadTemplate.txt")).getAbsolutePath(), classesJS.getAbsolutePath(), (new File(outputDirectory, "assets.epk")).getAbsolutePath(), (new File(outputDirectory, "EaglercraftX_1.8_Offline_en_US.html")).getAbsolutePath(), (new File(outputDirectory, "EaglercraftX_1.8_Offline_International.html")).getAbsolutePath(), diff --git a/buildtools/src/main/java/net/lax1dude/eaglercraft/v1_8/buildtools/gui/JavaC.java b/buildtools/src/main/java/net/lax1dude/eaglercraft/v1_8/buildtools/gui/JavaC.java index 9a74027b..9292ec35 100644 --- a/buildtools/src/main/java/net/lax1dude/eaglercraft/v1_8/buildtools/gui/JavaC.java +++ b/buildtools/src/main/java/net/lax1dude/eaglercraft/v1_8/buildtools/gui/JavaC.java @@ -37,7 +37,7 @@ public class JavaC { public static final ListPartly forked from Lucene tag releases/lucene-solr/8.5.1
- */
-public interface Accountable {
- /**
- * Allocated memory estimation
- *
- * @return Ram allocated in bytes
- */
- long ramBytesAllocated();
-
- /**
- * Bytes that is actually been used
- *
- * @return Ram used in bytes
- */
- long ramBytesUsed();
-}
diff --git a/sources/main/java/com/carrotsearch/hppc/ArraySizingStrategy.java b/sources/main/java/com/carrotsearch/hppc/ArraySizingStrategy.java
deleted file mode 100644
index b541c56f..00000000
--- a/sources/main/java/com/carrotsearch/hppc/ArraySizingStrategy.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * HPPC
- *
- * Copyright (C) 2010-2024 Carrot Search s.c. and contributors
- * All rights reserved.
- *
- * Refer to the full license file "LICENSE.txt":
- * https://github.com/carrotsearch/hppc/blob/master/LICENSE.txt
- */
-package com.carrotsearch.hppc;
-
-/** Resizing (growth) strategy for array-backed buffers. */
-public interface ArraySizingStrategy extends Accountable {
- /**
- * @param currentBufferLength Current size of the array (buffer). This number should comply with
- * the strategy's policies (it is a result of initial rounding or further growCalls). It can
- * also be zero, indicating the growth from an empty buffer.
- * @param elementsCount Number of elements stored in the buffer.
- * @param expectedAdditions Expected number of additions (resize hint).
- * @return Must return a new size at least as big as to hold
- * elementsCount + expectedAdditions
.
- * @throws BufferAllocationException If the sizing strategy cannot grow the buffer (for example
- * due to constraints or memory limits).
- */
- int grow(int currentBufferLength, int elementsCount, int expectedAdditions)
- throws BufferAllocationException;
-}
diff --git a/sources/main/java/com/carrotsearch/hppc/BitMixer.java b/sources/main/java/com/carrotsearch/hppc/BitMixer.java
deleted file mode 100644
index 136c12f9..00000000
--- a/sources/main/java/com/carrotsearch/hppc/BitMixer.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * HPPC
- *
- * Copyright (C) 2010-2024 Carrot Search s.c. and contributors
- * All rights reserved.
- *
- * Refer to the full license file "LICENSE.txt":
- * https://github.com/carrotsearch/hppc/blob/master/LICENSE.txt
- */
-package com.carrotsearch.hppc;
-
-/**
- * Bit mixing utilities. The purpose of these methods is to evenly distribute key space over int32
- * range.
- */
-public final class BitMixer {
-
- // Don't bother mixing very small key domains much.
- public static int mix(byte key) {
- return key * PHI_C32;
- }
-
- public static int mix(short key) {
- return mixPhi(key);
- }
-
- public static int mix(char key) {
- return mixPhi(key);
- }
-
- // Better mix for larger key domains.
- public static int mix(int key) {
- return mix32(key);
- }
-
- public static int mix(float key) {
- return mix32(Float.floatToIntBits(key));
- }
-
- public static int mix(double key) {
- return (int) mix64(Double.doubleToLongBits(key));
- }
-
- public static int mix(long key) {
- return (int) mix64(key);
- }
-
- public static int mix(Object key) {
- return key == null ? 0 : mix32(key.hashCode());
- }
-
- /** MH3's plain finalization step. */
- public static int mix32(int k) {
- k = (k ^ (k >>> 16)) * 0x85ebca6b;
- k = (k ^ (k >>> 13)) * 0xc2b2ae35;
- return k ^ (k >>> 16);
- }
-
- /**
- * Computes David Stafford variant 9 of 64bit mix function (MH3 finalization step, with different
- * shifts and constants).
- *
- *
Variant 9 is picked because it contains two 32-bit shifts which could be possibly optimized - * into better machine code. - * - * @see "http://zimbry.blogspot.com/2011/09/better-bit-mixing-improving-on.html" - */ - public static long mix64(long z) { - z = (z ^ (z >>> 32)) * 0x4cd6944c5cc20b6dL; - z = (z ^ (z >>> 29)) * 0xfc12c5b19d3259e9L; - return z ^ (z >>> 32); - } - - /* - * Golden ratio bit mixers. - */ - - private static final int PHI_C32 = 0x9e3779b9; - private static final long PHI_C64 = 0x9e3779b97f4a7c15L; - - public static int mixPhi(byte k) { - final int h = k * PHI_C32; - return h ^ (h >>> 16); - } - - public static int mixPhi(char k) { - final int h = k * PHI_C32; - return h ^ (h >>> 16); - } - - public static int mixPhi(short k) { - final int h = k * PHI_C32; - return h ^ (h >>> 16); - } - - public static int mixPhi(int k) { - final int h = k * PHI_C32; - return h ^ (h >>> 16); - } - - public static int mixPhi(float k) { - final int h = Float.floatToIntBits(k) * PHI_C32; - return h ^ (h >>> 16); - } - - public static int mixPhi(double k) { - final long h = Double.doubleToLongBits(k) * PHI_C64; - return (int) (h ^ (h >>> 32)); - } - - public static int mixPhi(long k) { - final long h = k * PHI_C64; - return (int) (h ^ (h >>> 32)); - } - - public static int mixPhi(Object k) { - final int h = (k == null ? 0 : k.hashCode() * PHI_C32); - return h ^ (h >>> 16); - } -} diff --git a/sources/main/java/com/carrotsearch/hppc/BitSet.java b/sources/main/java/com/carrotsearch/hppc/BitSet.java deleted file mode 100644 index 7f8a94bc..00000000 --- a/sources/main/java/com/carrotsearch/hppc/BitSet.java +++ /dev/null @@ -1,952 +0,0 @@ -/* - * HPPC - * - * Copyright (C) 2010-2024 Carrot Search s.c. and contributors - * All rights reserved. - * - * Refer to the full license file "LICENSE.txt": - * https://github.com/carrotsearch/hppc/blob/master/LICENSE.txt - */ -package com.carrotsearch.hppc; - -import com.carrotsearch.hppc.cursors.IntCursor; -import com.carrotsearch.hppc.cursors.LongCursor; -import com.carrotsearch.hppc.predicates.IntPredicate; -import com.carrotsearch.hppc.predicates.LongPredicate; -import com.carrotsearch.hppc.procedures.IntProcedure; -import com.carrotsearch.hppc.procedures.LongProcedure; -import java.util.*; - -/** - * An "open" BitSet implementation that allows direct access to the array of words storing the bits. - * - *
Unlike {@link java.util.BitSet}, the fact that bits are packed into an array of longs is part - * of the interface. This allows efficient implementation of other algorithms by someone other than - * the author. It also allows one to efficiently implement alternate serialization or interchange - * formats. - * - *
The index range for a bitset can easily exceed positive int
range in Java
- * (0x7fffffff), so many methods in this class accept or return a long
. There are
- * adapter methods that return views compatible with {@link LongLookupContainer} and {@link
- * IntLookupContainer} interfaces.
- *
- * @see #asIntLookupContainer()
- * @see #asLongLookupContainer()
- */
-public class BitSet implements Cloneable {
- /** The initial default number of bits. */
- private static final long DEFAULT_NUM_BITS = 64;
-
- /** Internal representation of bits in this bit set. */
- public long[] bits;
-
- /** The number of words (longs) used in the {@link #bits} array. */
- public int wlen;
-
- /** Constructs a bit set with the default capacity. */
- public BitSet() {
- this(DEFAULT_NUM_BITS);
- }
-
- /**
- * Constructs an BitSet large enough to hold numBits.
- *
- * @param numBits Number of bits
- */
- public BitSet(long numBits) {
- bits = new long[bits2words(numBits)];
- wlen = bits.length;
- }
-
- /**
- * Constructs an BitSet from an existing long[].
- *
- *
The first 64 bits are in long[0], with bit index 0 at the least significant bit, and bit - * index 63 at the most significant. Given a bit index, the word containing it is long[index/64], - * and it is at bit number index%64 within that word. - * - *
numWords are the number of elements in the array that contain set bits (non-zero longs). - * numWords should be <= bits.length, and any existing words in the array at position >= - * numWords should be zero. - * - * @param bits underlying bits buffer - * @param numWords the number of elements in the array that contain set bits - */ - public BitSet(long[] bits, int numWords) { - this.bits = bits; - this.wlen = numWords; - } - - /** - * Static constructor-like method similar to other (generic) collections. - * - * @return New instance. - */ - public static BitSet newInstance() { - return new BitSet(); - } - - /** - * @return Returns an iterator over all set bits of this bitset. The iterator should be faster - * than using a loop around {@link #nextSetBit(int)}. - */ - public BitSetIterator iterator() { - return new BitSetIterator(bits, wlen); - } - - /** - * @return Returns the current capacity in bits (1 greater than the index of the last bit). - */ - public long capacity() { - return bits.length << 6; - } - - /** - * @see #cardinality() - * @see java.util.BitSet#size() - * @return Returns the current capacity of this set. Included for compatibility. This is - * not equal to {@link #cardinality}. - */ - public long size() { - return capacity(); - } - - /** - * @see java.util.BitSet#length() - * @return Returns the "logical size" of this {@code BitSet}: the index of the highest set bit in - * the {@code BitSet} plus one. - */ - public long length() { - trimTrailingZeros(); - if (wlen == 0) return 0; - return (((long) wlen - 1) << 6) + (64 - Long.numberOfLeadingZeros(bits[wlen - 1])); - } - - /** - * @return Returns true if there are no set bits - */ - public boolean isEmpty() { - return cardinality() == 0; - } - - /** - * @param index The index. - * @return Returns true or false for the specified bit index. - */ - public boolean get(int index) { - int i = index >> 6; // div 64 - // signed shift will keep a negative index and force an - // array-index-out-of-bounds-exception, removing the need for an explicit check. - if (i >= bits.length) return false; - - int bit = index & 0x3f; // mod 64 - long bitmask = 1L << bit; - return (bits[i] & bitmask) != 0; - } - - /** - * @param index The index. - * @return Returns true or false for the specified bit index. - */ - public boolean get(long index) { - int i = (int) (index >> 6); // div 64 - if (i >= bits.length) return false; - int bit = (int) index & 0x3f; // mod 64 - long bitmask = 1L << bit; - return (bits[i] & bitmask) != 0; - } - - /** - * Sets a bit, expanding the set size if necessary. - * - * @param index the index to set - */ - public void set(long index) { - int wordNum = expandingWordNum(index); - int bit = (int) index & 0x3f; - long bitmask = 1L << bit; - bits[wordNum] |= bitmask; - } - - /** - * Sets a range of bits, expanding the set size if necessary - * - * @param startIndex lower index - * @param endIndex one-past the last bit to set - */ - public void set(long startIndex, long endIndex) { - if (endIndex <= startIndex) return; - - int startWord = (int) (startIndex >> 6); - - // since endIndex is one past the end, this is index of the last - // word to be changed. - int endWord = expandingWordNum(endIndex - 1); - - long startmask = -1L << startIndex; - long endmask = -1L >>> -endIndex; // 64-(endIndex&0x3f) is the same as -endIndex - // due to wrap - - if (startWord == endWord) { - bits[startWord] |= (startmask & endmask); - return; - } - - bits[startWord] |= startmask; - Arrays.fill(bits, startWord + 1, endWord, -1L); - bits[endWord] |= endmask; - } - - protected int expandingWordNum(long index) { - int wordNum = (int) (index >> 6); - if (wordNum >= wlen) { - ensureCapacity(index + 1); - wlen = wordNum + 1; - } - return wordNum; - } - - /** Clears all bits. */ - public void clear() { - Arrays.fill(bits, 0); - this.wlen = 0; - } - - /** - * clears a bit, allowing access beyond the current set size without changing the size. - * - * @param index the index to clear - */ - public void clear(long index) { - int wordNum = (int) (index >> 6); // div 64 - if (wordNum >= wlen) return; - int bit = (int) index & 0x3f; // mod 64 - long bitmask = 1L << bit; - bits[wordNum] &= ~bitmask; - } - - /** - * Clears a range of bits. Clearing past the end does not change the size of the set. - * - * @param startIndex lower index - * @param endIndex one-past the last bit to clear - */ - public void clear(int startIndex, int endIndex) { - if (endIndex <= startIndex) return; - - int startWord = (startIndex >> 6); - if (startWord >= wlen) return; - - // since endIndex is one past the end, this is index of the last - // word to be changed. - int endWord = ((endIndex - 1) >> 6); - - long startmask = -1L << startIndex; - long endmask = -1L >>> -endIndex; // 64-(endIndex&0x3f) is the same as -endIndex - // due to wrap - - // invert masks since we are clearing - startmask = ~startmask; - endmask = ~endmask; - - if (startWord == endWord) { - bits[startWord] &= (startmask | endmask); - return; - } - - bits[startWord] &= startmask; - - int middle = Math.min(wlen, endWord); - Arrays.fill(bits, startWord + 1, middle, 0L); - if (endWord < wlen) { - bits[endWord] &= endmask; - } - } - - /** - * Clears a range of bits. Clearing past the end does not change the size of the set. - * - * @param startIndex lower index - * @param endIndex one-past the last bit to clear - */ - public void clear(long startIndex, long endIndex) { - if (endIndex <= startIndex) return; - - int startWord = (int) (startIndex >> 6); - if (startWord >= wlen) return; - - // since endIndex is one past the end, this is index of the last - // word to be changed. - int endWord = (int) ((endIndex - 1) >> 6); - - long startmask = -1L << startIndex; - long endmask = -1L >>> -endIndex; // 64-(endIndex&0x3f) is the same as -endIndex - // due to wrap - - // invert masks since we are clearing - startmask = ~startmask; - endmask = ~endmask; - - if (startWord == endWord) { - bits[startWord] &= (startmask | endmask); - return; - } - - bits[startWord] &= startmask; - - int middle = Math.min(wlen, endWord); - Arrays.fill(bits, startWord + 1, middle, 0L); - if (endWord < wlen) { - bits[endWord] &= endmask; - } - } - - /** - * Sets a bit and returns the previous value. The index should be less than the BitSet size. - * - * @param index the index to set - * @return previous state of the index - */ - public boolean getAndSet(int index) { - int wordNum = index >> 6; // div 64 - int bit = index & 0x3f; // mod 64 - long bitmask = 1L << bit; - boolean val = (bits[wordNum] & bitmask) != 0; - bits[wordNum] |= bitmask; - return val; - } - - /** - * Sets a bit and returns the previous value. The index should be less than the BitSet size. - * - * @param index the index to set - * @return previous state of the index - */ - public boolean getAndSet(long index) { - int wordNum = (int) (index >> 6); // div 64 - int bit = (int) index & 0x3f; // mod 64 - long bitmask = 1L << bit; - boolean val = (bits[wordNum] & bitmask) != 0; - bits[wordNum] |= bitmask; - return val; - } - - /** - * Flips a bit, expanding the set size if necessary. - * - * @param index the index to flip - */ - public void flip(long index) { - int wordNum = expandingWordNum(index); - int bit = (int) index & 0x3f; // mod 64 - long bitmask = 1L << bit; - bits[wordNum] ^= bitmask; - } - - /** - * flips a bit and returns the resulting bit value. The index should be less than the BitSet size. - * - * @param index the index to flip - * @return previous state of the index - */ - public boolean flipAndGet(int index) { - int wordNum = index >> 6; // div 64 - int bit = index & 0x3f; // mod 64 - long bitmask = 1L << bit; - bits[wordNum] ^= bitmask; - return (bits[wordNum] & bitmask) != 0; - } - - /** - * flips a bit and returns the resulting bit value. The index should be less than the BitSet size. - * - * @param index the index to flip - * @return previous state of the index - */ - public boolean flipAndGet(long index) { - int wordNum = (int) (index >> 6); // div 64 - int bit = (int) index & 0x3f; // mod 64 - long bitmask = 1L << bit; - bits[wordNum] ^= bitmask; - return (bits[wordNum] & bitmask) != 0; - } - - /** - * Flips a range of bits, expanding the set size if necessary - * - * @param startIndex lower index - * @param endIndex one-past the last bit to flip - */ - public void flip(long startIndex, long endIndex) { - if (endIndex <= startIndex) return; - int startWord = (int) (startIndex >> 6); - - // since endIndex is one past the end, this is index of the last - // word to be changed. - int endWord = expandingWordNum(endIndex - 1); - - long startmask = -1L << startIndex; - long endmask = -1L >>> -endIndex; // 64-(endIndex&0x3f) is the same as -endIndex - // due to wrap - - if (startWord == endWord) { - bits[startWord] ^= (startmask & endmask); - return; - } - - bits[startWord] ^= startmask; - - for (int i = startWord + 1; i < endWord; i++) { - bits[i] = ~bits[i]; - } - - bits[endWord] ^= endmask; - } - - /** - * @return the number of set bits - */ - public long cardinality() { - return BitUtil.pop_array(bits, 0, wlen); - } - - /** - * @param a The first set - * @param b The second set - * @return Returns the popcount or cardinality of the intersection of the two sets. Neither set is - * modified. - */ - public static long intersectionCount(BitSet a, BitSet b) { - return BitUtil.pop_intersect(a.bits, b.bits, 0, Math.min(a.wlen, b.wlen)); - } - - /** - * @param a The first set - * @param b The second set - * @return Returns the popcount or cardinality of the union of the two sets. Neither set is - * modified. - */ - public static long unionCount(BitSet a, BitSet b) { - long tot = BitUtil.pop_union(a.bits, b.bits, 0, Math.min(a.wlen, b.wlen)); - if (a.wlen < b.wlen) { - tot += BitUtil.pop_array(b.bits, a.wlen, b.wlen - a.wlen); - } else if (a.wlen > b.wlen) { - tot += BitUtil.pop_array(a.bits, b.wlen, a.wlen - b.wlen); - } - return tot; - } - - /** - * @param a The first set - * @param b The second set - * @return Returns the popcount or cardinality of "a and not b" or "intersection(a, not(b))". - * Neither set is modified. - */ - public static long andNotCount(BitSet a, BitSet b) { - long tot = BitUtil.pop_andnot(a.bits, b.bits, 0, Math.min(a.wlen, b.wlen)); - if (a.wlen > b.wlen) { - tot += BitUtil.pop_array(a.bits, b.wlen, a.wlen - b.wlen); - } - return tot; - } - - /** - * @param a The first set - * @param b The second set - * @return Returns the popcount or cardinality of the exclusive-or of the two sets. Neither set is - * modified. - */ - public static long xorCount(BitSet a, BitSet b) { - long tot = BitUtil.pop_xor(a.bits, b.bits, 0, Math.min(a.wlen, b.wlen)); - if (a.wlen < b.wlen) { - tot += BitUtil.pop_array(b.bits, a.wlen, b.wlen - a.wlen); - } else if (a.wlen > b.wlen) { - tot += BitUtil.pop_array(a.bits, b.wlen, a.wlen - b.wlen); - } - return tot; - } - - /** - * @param index The index to start scanning from, inclusive. - * @return Returns the index of the first set bit starting at the index specified. -1 is returned - * if there are no more set bits. - */ - public int nextSetBit(int index) { - int i = index >> 6; - if (i >= wlen) return -1; - int subIndex = index & 0x3f; // index within the word - long word = bits[i] >> subIndex; // skip all the bits to the right of index - - if (word != 0) { - return (i << 6) + subIndex + Long.numberOfTrailingZeros(word); - } - - while (++i < wlen) { - word = bits[i]; - if (word != 0) return (i << 6) + Long.numberOfTrailingZeros(word); - } - - return -1; - } - - /** - * @param index The index to start scanning from, inclusive. - * @return Returns the index of the first set bit starting at the index specified. -1 is returned - * if there are no more set bits. - */ - public long nextSetBit(long index) { - int i = (int) (index >>> 6); - if (i >= wlen) return -1; - int subIndex = (int) index & 0x3f; // index within the word - long word = bits[i] >>> subIndex; // skip all the bits to the right of index - - if (word != 0) { - return (((long) i) << 6) + (subIndex + Long.numberOfTrailingZeros(word)); - } - - while (++i < wlen) { - word = bits[i]; - if (word != 0) return (((long) i) << 6) + Long.numberOfTrailingZeros(word); - } - - return -1; - } - - @Override - public Object clone() { - try { - BitSet obs = (BitSet) super.clone(); - obs.bits = (long[]) obs.bits.clone(); // hopefully an array clone is as - // fast(er) than arraycopy - return obs; - } catch (CloneNotSupportedException e) { - throw new RuntimeException(e); - } - } - - /** - * this = this AND other - * - * @param other The bitset to intersect with. - */ - public void intersect(BitSet other) { - int newLen = Math.min(this.wlen, other.wlen); - long[] thisArr = this.bits; - long[] otherArr = other.bits; - // testing against zero can be more efficient - int pos = newLen; - while (--pos >= 0) { - thisArr[pos] &= otherArr[pos]; - } - if (this.wlen > newLen) { - // fill zeros from the new shorter length to the old length - Arrays.fill(bits, newLen, this.wlen, 0); - } - this.wlen = newLen; - } - - /** - * this = this OR other - * - * @param other The bitset to union with. - */ - public void union(BitSet other) { - int newLen = Math.max(wlen, other.wlen); - ensureCapacityWords(newLen); - - long[] thisArr = this.bits; - long[] otherArr = other.bits; - int pos = Math.min(wlen, other.wlen); - while (--pos >= 0) { - thisArr[pos] |= otherArr[pos]; - } - if (this.wlen < newLen) { - System.arraycopy(otherArr, this.wlen, thisArr, this.wlen, newLen - this.wlen); - } - this.wlen = newLen; - } - - /** - * Remove all elements set in other: this = this AND_NOT other - * - * @param other The other bitset. - */ - public void remove(BitSet other) { - int idx = Math.min(wlen, other.wlen); - long[] thisArr = this.bits; - long[] otherArr = other.bits; - while (--idx >= 0) { - thisArr[idx] &= ~otherArr[idx]; - } - } - - /** - * this = this XOR other - * - * @param other The other bitset. - */ - public void xor(BitSet other) { - int newLen = Math.max(wlen, other.wlen); - ensureCapacityWords(newLen); - - long[] thisArr = this.bits; - long[] otherArr = other.bits; - int pos = Math.min(wlen, other.wlen); - while (--pos >= 0) { - thisArr[pos] ^= otherArr[pos]; - } - if (this.wlen < newLen) { - System.arraycopy(otherArr, this.wlen, thisArr, this.wlen, newLen - this.wlen); - } - this.wlen = newLen; - } - - // some BitSet compatibility methods - - // ** see {@link intersect} */ - public void and(BitSet other) { - intersect(other); - } - - // ** see {@link union} */ - public void or(BitSet other) { - union(other); - } - - // ** see {@link andNot} */ - public void andNot(BitSet other) { - remove(other); - } - - /** - * @param other The other bitset. - * @return true if the sets have any elements in common - */ - public boolean intersects(BitSet other) { - int pos = Math.min(this.wlen, other.wlen); - long[] thisArr = this.bits; - long[] otherArr = other.bits; - while (--pos >= 0) { - if ((thisArr[pos] & otherArr[pos]) != 0) return true; - } - return false; - } - - /** - * Expand the long[] with the size given as a number of words (64 bit longs). getNumWords() is - * unchanged by this call. - * - * @param numWords The size to expand to (64-bit long words) - */ - public void ensureCapacityWords(int numWords) { - if (bits.length < numWords) { - bits = grow(bits, numWords); - } - } - - public static long[] grow(long[] array, int minSize) { - if (array.length < minSize) { - long[] newArray = new long[getNextSize(minSize)]; - System.arraycopy(array, 0, newArray, 0, array.length); - return newArray; - } else return array; - } - - public static int getNextSize(int targetSize) { - /* - * This over-allocates proportional to the list size, making room for additional - * growth. The over-allocation is mild, but is enough to give linear-time - * amortized behavior over a long sequence of appends() in the presence of a - * poorly-performing system realloc(). The growth pattern is: 0, 4, 8, 16, 25, 35, - * 46, 58, 72, 88, ... - */ - return (targetSize >> 3) + (targetSize < 9 ? 3 : 6) + targetSize; - } - - /** - * Ensure that the long[] is big enough to hold numBits, expanding it if necessary. getNumWords() - * is unchanged by this call. - * - * @param numBits The number of bits to expand to - */ - public void ensureCapacity(long numBits) { - ensureCapacityWords(bits2words(numBits)); - } - - /** Lowers {@link #wlen}, the number of words in use, by checking for trailing zero words. */ - public void trimTrailingZeros() { - int idx = wlen - 1; - while (idx >= 0 && bits[idx] == 0) idx--; - wlen = idx + 1; - } - - /* - * returns the number of 64 bit words it would take to hold numBits - */ - public static int bits2words(long numBits) { - return (int) (((numBits - 1) >>> 6) + 1); - } - - /* returns true if both sets have the same bits set */ - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof BitSet)) return false; - - BitSet a; - BitSet b = (BitSet) o; - - // make a the larger set. - if (b.wlen > this.wlen) { - a = b; - b = this; - } else { - a = this; - } - - // check for any set bits out of the range of b - for (int i = a.wlen - 1; i >= b.wlen; i--) { - if (a.bits[i] != 0) return false; - } - - for (int i = b.wlen - 1; i >= 0; i--) { - if (a.bits[i] != b.bits[i]) return false; - } - - return true; - } - - @Override - public int hashCode() { - // Start with a zero hash and use a mix that results in zero if the input is zero. - // This effectively truncates trailing zeros without an explicit check. - long h = 0; - for (int i = bits.length; --i >= 0; ) { - h ^= bits[i]; - h = (h << 1) | (h >>> 63); // rotate left - } - - // fold leftmost bits into right and add a constant to prevent - // empty sets from returning 0, which is too common. - return (int) ((h >> 32) ^ h) + 0x98761234; - } - - @Override - public String toString() { - long bit = nextSetBit(0); - if (bit < 0) { - return "{}"; - } - - final StringBuilder builder = new StringBuilder(); - builder.append("{"); - - builder.append(Long.toString(bit)); - while ((bit = nextSetBit(bit + 1)) >= 0) { - builder.append(", "); - builder.append(Long.toString(bit)); - } - builder.append("}"); - - return builder.toString(); - } - - /** - * Returns a view over this bitset data compatible with {@link IntLookupContainer}. A new object - * is always returned, but its methods reflect the current state of the bitset (the view is not a - * snapshot). - * - *
Methods of the returned {@link IntLookupContainer} may throw a {@link RuntimeException} if
- * the cardinality of this bitset exceeds the int range.
- *
- * @return The view of this bitset as {@link IntLookupContainer}.
- */
- public IntLookupContainer asIntLookupContainer() {
- return new IntLookupContainer() {
- @Override
- public int size() {
- return getCurrentCardinality();
- }
-
- @Override
- public boolean isEmpty() {
- return BitSet.this.isEmpty();
- }
-
- @Override
- public Iterator def int_table(): tbl = [ hex(bits2int(val)).strip('L') for val in range(256) ] return
- * ','.join(tbl) ****
- */
-
- // hmmm, what about an iterator that finds zeros though,
- // or a reverse iterator... should they be separate classes
- // for efficiency, or have a common root interface? (or
- // maybe both? could ask for a SetBitsIterator, etc...
-
- private final long[] arr;
-
- private final int words;
- private int i = -1;
- private long word;
- private int wordShift;
- private int indexArray;
-
- public BitSetIterator(BitSet obs) {
- this(obs.bits, obs.wlen);
- }
-
- public BitSetIterator(long[] bits, int numWords) {
- arr = bits;
- words = numWords;
- }
-
- // 64 bit shifts
- private void shift() {
- if ((int) word == 0) {
- wordShift += 32;
- word = word >>> 32;
- }
- if ((word & 0x0000FFFF) == 0) {
- wordShift += 16;
- word >>>= 16;
- }
- if ((word & 0x000000FF) == 0) {
- wordShift += 8;
- word >>>= 8;
- }
- indexArray = bitlist[(int) word & 0xff];
- }
-
- public static final int NO_MORE = -1;
-
- public int nextSetBit() {
- if (indexArray == 0) {
- if (word != 0) {
- word >>>= 8;
- wordShift += 8;
- }
-
- while (word == 0) {
- if (++i >= words) {
- return NO_MORE;
- }
- word = arr[i];
- wordShift = -1; // loop invariant code motion should move this
- }
-
- // after the first time, should I go with a linear search, or
- // stick with the binary search in shift?
- shift();
- }
-
- int bitIndex = (indexArray & 0x0f) + wordShift;
- indexArray >>>= 4;
- // should i<<6 be cached as a separate variable?
- // it would only save one cycle in the best circumstances.
- return (i << 6) + bitIndex;
- }
-}
diff --git a/sources/main/java/com/carrotsearch/hppc/BitUtil.java b/sources/main/java/com/carrotsearch/hppc/BitUtil.java
deleted file mode 100644
index 61a628d5..00000000
--- a/sources/main/java/com/carrotsearch/hppc/BitUtil.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * HPPC
- *
- * Copyright (C) 2010-2024 Carrot Search s.c. and contributors
- * All rights reserved.
- *
- * Refer to the full license file "LICENSE.txt":
- * https://github.com/carrotsearch/hppc/blob/master/LICENSE.txt
- */
-package com.carrotsearch.hppc;
-
-/** A variety of high efficiency bit twiddling routines. */
-final class BitUtil {
- private BitUtil() {} // no instance
-
- // The pop methods used to rely on bit-manipulation tricks for speed but it
- // turns out that it is faster to use the Long.bitCount method (which is an
- // intrinsic since Java 6u18) in a naive loop, see LUCENE-2221
-
- /** Returns the number of set bits in an array of longs. */
- public static long pop_array(long[] arr, int wordOffset, int numWords) {
- long popCount = 0;
- for (int i = wordOffset, end = wordOffset + numWords; i < end; ++i) {
- popCount += Long.bitCount(arr[i]);
- }
- return popCount;
- }
-
- /**
- * Returns the popcount or cardinality of the two sets after an intersection. Neither array is
- * modified.
- */
- public static long pop_intersect(long[] arr1, long[] arr2, int wordOffset, int numWords) {
- long popCount = 0;
- for (int i = wordOffset, end = wordOffset + numWords; i < end; ++i) {
- popCount += Long.bitCount(arr1[i] & arr2[i]);
- }
- return popCount;
- }
-
- /** Returns the popcount or cardinality of the union of two sets. Neither array is modified. */
- public static long pop_union(long[] arr1, long[] arr2, int wordOffset, int numWords) {
- long popCount = 0;
- for (int i = wordOffset, end = wordOffset + numWords; i < end; ++i) {
- popCount += Long.bitCount(arr1[i] | arr2[i]);
- }
- return popCount;
- }
-
- /** Returns the popcount or cardinality of A & ~B. Neither array is modified. */
- public static long pop_andnot(long[] arr1, long[] arr2, int wordOffset, int numWords) {
- long popCount = 0;
- for (int i = wordOffset, end = wordOffset + numWords; i < end; ++i) {
- popCount += Long.bitCount(arr1[i] & ~arr2[i]);
- }
- return popCount;
- }
-
- /** Returns the popcount or cardinality of A ^ B Neither array is modified. */
- public static long pop_xor(long[] arr1, long[] arr2, int wordOffset, int numWords) {
- long popCount = 0;
- for (int i = wordOffset, end = wordOffset + numWords; i < end; ++i) {
- popCount += Long.bitCount(arr1[i] ^ arr2[i]);
- }
- return popCount;
- }
-
- /**
- * returns the next highest power of two, or the current value if it's already a power of two or
- * zero
- */
- public static int nextHighestPowerOfTwo(int v) {
- v--;
- v |= v >> 1;
- v |= v >> 2;
- v |= v >> 4;
- v |= v >> 8;
- v |= v >> 16;
- v++;
- return v;
- }
-
- /**
- * returns the next highest power of two, or the current value if it's already a power of two or
- * zero
- */
- public static long nextHighestPowerOfTwo(long v) {
- v--;
- v |= v >> 1;
- v |= v >> 2;
- v |= v >> 4;
- v |= v >> 8;
- v |= v >> 16;
- v |= v >> 32;
- v++;
- return v;
- }
-}
diff --git a/sources/main/java/com/carrotsearch/hppc/BoundedProportionalArraySizingStrategy.java b/sources/main/java/com/carrotsearch/hppc/BoundedProportionalArraySizingStrategy.java
deleted file mode 100644
index 14c5a9ab..00000000
--- a/sources/main/java/com/carrotsearch/hppc/BoundedProportionalArraySizingStrategy.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * HPPC
- *
- * Copyright (C) 2010-2024 Carrot Search s.c. and contributors
- * All rights reserved.
- *
- * Refer to the full license file "LICENSE.txt":
- * https://github.com/carrotsearch/hppc/blob/master/LICENSE.txt
- */
-package com.carrotsearch.hppc;
-
-import java.util.ArrayList;
-
-/**
- * Array resizing proportional to the current buffer size, optionally kept within the given minimum
- * and maximum growth limits. Java's {@link ArrayList} uses:
- *
- * This method is handy, but costly if used in tight loops (anonymous array passing)
- *
- * @param elements The elements to add.
- */
- public final void addFirst(byte... elements) {
- ensureBufferSpace(elements.length);
- for (byte k : elements) {
- addFirst(k);
- }
- }
-
- /**
- * Inserts all elements from the given container to the front of this deque.
- *
- * @param container The container to iterate over.
- * @return Returns the number of elements actually added as a result of this call.
- */
- public int addFirst(ByteContainer container) {
- int size = container.size();
- ensureBufferSpace(size);
-
- for (ByteCursor cursor : container) {
- addFirst(cursor.value);
- }
-
- return size;
- }
-
- /**
- * Inserts all elements from the given iterable to the front of this deque.
- *
- * @param iterable The iterable to iterate over.
- * @return Returns the number of elements actually added as a result of this call.
- */
- public int addFirst(Iterable extends ByteCursor> iterable) {
- int size = 0;
- for (ByteCursor cursor : iterable) {
- addFirst(cursor.value);
- size++;
- }
- return size;
- }
-
- /** {@inheritDoc} */
- @Override
- public void addLast(byte e1) {
- int t = oneRight(tail, buffer.length);
- if (head == t) {
- ensureBufferSpace(1);
- t = oneRight(tail, buffer.length);
- }
- buffer[tail] = e1;
- tail = t;
- }
-
- /**
- * Vararg-signature method for adding elements at the end of this deque.
- *
- * This method is handy, but costly if used in tight loops (anonymous array passing)
- *
- * @param elements The elements to iterate over.
- */
- public final void addLast(byte... elements) {
- ensureBufferSpace(1);
- for (byte k : elements) {
- addLast(k);
- }
- }
-
- /**
- * Inserts all elements from the given container to the end of this deque.
- *
- * @param container The container to iterate over.
- * @return Returns the number of elements actually added as a result of this call.
- */
- public int addLast(ByteContainer container) {
- int size = container.size();
- ensureBufferSpace(size);
-
- for (ByteCursor cursor : container) {
- addLast(cursor.value);
- }
-
- return size;
- }
-
- /**
- * Inserts all elements from the given iterable to the end of this deque.
- *
- * @param iterable The iterable to iterate over.
- * @return Returns the number of elements actually added as a result of this call.
- */
- public int addLast(Iterable extends ByteCursor> iterable) {
- int size = 0;
- for (ByteCursor cursor : iterable) {
- addLast(cursor.value);
- size++;
- }
- return size;
- }
-
- /** {@inheritDoc} */
- @Override
- public byte removeFirst() {
- assert size() > 0 : "The deque is empty.";
-
- final byte result = buffer[head];
- buffer[head] = ((byte) 0);
- head = oneRight(head, buffer.length);
- return result;
- }
-
- /** {@inheritDoc} */
- @Override
- public byte removeLast() {
- assert size() > 0 : "The deque is empty.";
-
- tail = oneLeft(tail, buffer.length);
- final byte result = buffer[tail];
- buffer[tail] = ((byte) 0);
- return result;
- }
-
- /** {@inheritDoc} */
- @Override
- public byte getFirst() {
- assert size() > 0 : "The deque is empty.";
-
- return buffer[head];
- }
-
- /** {@inheritDoc} */
- @Override
- public byte getLast() {
- assert size() > 0 : "The deque is empty.";
-
- return buffer[oneLeft(tail, buffer.length)];
- }
-
- /** {@inheritDoc} */
- @Override
- public int removeFirst(byte e1) {
- final int index = bufferIndexOf(e1);
- if (index >= 0) removeAtBufferIndex(index);
- return index;
- }
-
- /**
- * Return the index of the first (counting from head) element equal to The internal array buffers are not released as a result of this call.
- *
- * @see #release()
- */
- @Override
- public void clear() {
- if (head < tail) {
- Arrays.fill(buffer, head, tail, ((byte) 0));
- } else {
- Arrays.fill(buffer, 0, tail, ((byte) 0));
- Arrays.fill(buffer, head, buffer.length, ((byte) 0));
- }
- this.head = tail = 0;
- }
-
- /** Release internal buffers of this deque and reallocate with the default buffer. */
- public void release() {
- this.head = tail = 0;
- buffer = ByteArrayList.EMPTY_ARRAY;
- ensureBufferSpace(0);
- }
-
- /**
- * Ensure this container can hold at least the given number of elements without resizing its
- * buffers.
- *
- * @param expectedElements The total number of elements, inclusive.
- */
- @Override
- public void ensureCapacity(int expectedElements) {
- ensureBufferSpace(expectedElements - size());
- }
-
- /**
- * Ensures the internal buffer has enough free slots to store This method is handy, but costly if used in tight loops (anonymous array passing)
- */
- public final void add(byte... elements) {
- add(elements, 0, elements.length);
- }
-
- /** Adds all elements from another container. */
- public int addAll(ByteContainer container) {
- final int size = container.size();
- ensureBufferSpace(size);
-
- for (ByteCursor cursor : container) {
- add(cursor.value);
- }
-
- return size;
- }
-
- /** Adds all elements from another iterable. */
- public int addAll(Iterable extends ByteCursor> iterable) {
- int size = 0;
- for (ByteCursor cursor : iterable) {
- add(cursor.value);
- size++;
- }
- return size;
- }
-
- /** {@inheritDoc} */
- @Override
- public void insert(int index, byte e1) {
- assert (index >= 0 && index <= size())
- : "Index " + index + " out of bounds [" + 0 + ", " + size() + "].";
-
- ensureBufferSpace(1);
- System.arraycopy(buffer, index, buffer, index + 1, elementsCount - index);
- buffer[index] = e1;
- elementsCount++;
- }
-
- /** {@inheritDoc} */
- @Override
- public byte get(int index) {
- assert (index >= 0 && index < size())
- : "Index " + index + " out of bounds [" + 0 + ", " + size() + ").";
-
- return buffer[index];
- }
-
- /** {@inheritDoc} */
- @Override
- public byte set(int index, byte e1) {
- assert (index >= 0 && index < size())
- : "Index " + index + " out of bounds [" + 0 + ", " + size() + ").";
-
- final byte v = buffer[index];
- buffer[index] = e1;
- return v;
- }
-
- /** {@inheritDoc} */
- @Override
- public byte removeAt(int index) {
- assert (index >= 0 && index < size())
- : "Index " + index + " out of bounds [" + 0 + ", " + size() + ").";
-
- final byte v = buffer[index];
- System.arraycopy(buffer, index + 1, buffer, index, --elementsCount - index);
-
- return v;
- }
-
- /** {@inheritDoc} */
- @Override
- public byte removeLast() {
- assert elementsCount > 0;
-
- final byte v = buffer[--elementsCount];
-
- return v;
- }
-
- /** {@inheritDoc} */
- @Override
- public void removeRange(int fromIndex, int toIndex) {
- assert (fromIndex >= 0 && fromIndex <= size())
- : "Index " + fromIndex + " out of bounds [" + 0 + ", " + size() + ").";
- assert (toIndex >= 0 && toIndex <= size())
- : "Index " + toIndex + " out of bounds [" + 0 + ", " + size() + "].";
- assert fromIndex <= toIndex : "fromIndex must be <= toIndex: " + fromIndex + ", " + toIndex;
-
- System.arraycopy(buffer, toIndex, buffer, fromIndex, elementsCount - toIndex);
- final int count = toIndex - fromIndex;
- elementsCount -= count;
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean removeElement(byte e1) {
- return removeFirst(e1) != -1;
- }
-
- /** {@inheritDoc} */
- @Override
- public int removeFirst(byte e1) {
- final int index = indexOf(e1);
- if (index >= 0) removeAt(index);
- return index;
- }
-
- /** {@inheritDoc} */
- @Override
- public int removeLast(byte e1) {
- final int index = lastIndexOf(e1);
- if (index >= 0) removeAt(index);
- return index;
- }
-
- /** {@inheritDoc} */
- @Override
- public int removeAll(byte e1) {
- int to = 0;
- for (int from = 0; from < elementsCount; from++) {
- if (((e1) == (buffer[from]))) {
- continue;
- }
- if (to != from) {
- buffer[to] = buffer[from];
- }
- to++;
- }
- final int deleted = elementsCount - to;
- this.elementsCount = to;
-
- return deleted;
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean contains(byte e1) {
- return indexOf(e1) >= 0;
- }
-
- /** {@inheritDoc} */
- @Override
- public int indexOf(byte e1) {
- for (int i = 0; i < elementsCount; i++) {
- if (((e1) == (buffer[i]))) {
- return i;
- }
- }
-
- return -1;
- }
-
- /** {@inheritDoc} */
- @Override
- public int lastIndexOf(byte e1) {
- for (int i = elementsCount - 1; i >= 0; i--) {
- if (((e1) == (buffer[i]))) {
- return i;
- }
- }
-
- return -1;
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean isEmpty() {
- return elementsCount == 0;
- }
-
- /**
- * Ensure this container can hold at least the given number of elements without resizing its
- * buffers.
- *
- * @param expectedElements The total number of elements, inclusive.
- */
- @Override
- public void ensureCapacity(int expectedElements) {
- final int bufferLen = (buffer == null ? 0 : buffer.length);
- if (expectedElements > bufferLen) {
- ensureBufferSpace(expectedElements - size());
- }
- }
-
- /**
- * Ensures the internal buffer has enough free slots to store The returned array is sized to match exactly the number of elements of the stack.
- */
- @Override
- public byte[] toArray() {
-
- return Arrays.copyOf(buffer, elementsCount);
- }
-
- /** {@inheritDoc} */
- @Override
- public ByteIndexedContainer sort() {
- Arrays.sort(buffer, 0, elementsCount);
- return this;
- }
-
- /** {@inheritDoc} */
- @Override
- public ByteIndexedContainer reverse() {
- for (int i = 0, mid = elementsCount >> 1, j = elementsCount - 1; i < mid; i++, j--) {
- byte tmp = buffer[i];
- buffer[i] = buffer[j];
- buffer[j] = tmp;
- }
- return this;
- }
-
- /**
- * Clone this object. The returned clone will reuse the same hash function and array resizing
- * strategy.
- */
- @Override
- public ByteArrayList clone() {
- try {
-
- final ByteArrayList cloned = (ByteArrayList) super.clone();
- cloned.buffer = buffer.clone();
- return cloned;
- } catch (CloneNotSupportedException e) {
- throw new RuntimeException(e);
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public int hashCode() {
- int h = 1, max = elementsCount;
- for (int i = 0; i < max; i++) {
- h = 31 * h + BitMixer.mix(this.buffer[i]);
- }
- return h;
- }
-
- /**
- * Returns The iterator is implemented as a cursor and it returns the same cursor instance on
- * every call to {@link Iterator#next()} (to avoid boxing of primitive types). To read the current
- * list's value (or index in the list) use the cursor's public fields. An example is shown below.
- *
- * The returned array is always a copy, regardless of the storage used by the container.
- */
- public byte[] toArray();
-
- /**
- * Applies a This method is handy, but costly if used in tight loops (anonymous array passing)
- */
- public final void push(byte... elements) {
- push(elements, 0, elements.length);
- }
-
- /** Pushes all elements from another container to the top of the stack. */
- public int pushAll(ByteContainer container) {
- return addAll(container);
- }
-
- /** Pushes all elements from another iterable to the top of the stack. */
- public int pushAll(Iterable extends ByteCursor> iterable) {
- return addAll(iterable);
- }
-
- /** Discard an arbitrary number of elements from the top of the stack. */
- public void discard(int count) {
- assert elementsCount >= count;
-
- elementsCount -= count;
- }
-
- /** Discard the top element from the stack. */
- public void discard() {
- assert elementsCount > 0;
-
- elementsCount--;
- }
-
- /** Remove the top element from the stack and return it. */
- public byte pop() {
- return removeLast();
- }
-
- /** Peek at the top element on the stack. */
- public byte peek() {
- assert elementsCount > 0;
- return buffer[elementsCount - 1];
- }
-
- /** Create a stack by pushing a variable number of arguments to it. */
- public static ByteStack from(byte... elements) {
- final ByteStack stack = new ByteStack(elements.length);
- stack.push(elements);
- return stack;
- }
-
- /** {@inheritDoc} */
- @Override
- public ByteStack clone() {
- return (ByteStack) super.clone();
- }
-}
diff --git a/sources/main/java/com/carrotsearch/hppc/CharArrayDeque.java b/sources/main/java/com/carrotsearch/hppc/CharArrayDeque.java
deleted file mode 100644
index e8aeb6a4..00000000
--- a/sources/main/java/com/carrotsearch/hppc/CharArrayDeque.java
+++ /dev/null
@@ -1,776 +0,0 @@
-package com.carrotsearch.hppc;
-
-import static com.carrotsearch.hppc.Containers.*;
-
-import com.carrotsearch.hppc.cursors.CharCursor;
-import com.carrotsearch.hppc.predicates.CharPredicate;
-import com.carrotsearch.hppc.procedures.CharProcedure;
-import java.util.*;
-
-/** An array-backed {@link CharDeque}. */
-@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeArrayDeque.java")
-public class CharArrayDeque extends AbstractCharCollection
- implements CharDeque, Preallocable, Cloneable, Accountable {
-
- /** Reuse the same strategy instance. */
- private static final BoundedProportionalArraySizingStrategy DEFAULT_SIZING_STRATEGY =
- BoundedProportionalArraySizingStrategy.DEFAULT_INSTANCE;
-
- /** Internal array for storing elements of the deque. */
- public char[] buffer = CharArrayList.EMPTY_ARRAY;
-
- /**
- * The index of the element at the head of the deque or an arbitrary number equal to tail if the
- * deque is empty.
- */
- public int head;
-
- /** The index at which the next element would be added to the tail of the deque. */
- public int tail;
-
- /** Buffer resizing strategy. */
- protected final ArraySizingStrategy resizer;
-
- /** New instance with sane defaults. */
- public CharArrayDeque() {
- this(DEFAULT_EXPECTED_ELEMENTS);
- }
-
- /**
- * New instance with sane defaults.
- *
- * @param expectedElements The expected number of elements guaranteed not to cause buffer
- * expansion (inclusive).
- */
- public CharArrayDeque(int expectedElements) {
- this(expectedElements, DEFAULT_SIZING_STRATEGY);
- }
-
- /**
- * New instance with sane defaults.
- *
- * @param expectedElements The expected number of elements guaranteed not to cause buffer
- * expansion (inclusive).
- * @param resizer Underlying buffer sizing strategy.
- */
- public CharArrayDeque(int expectedElements, ArraySizingStrategy resizer) {
- assert resizer != null;
- this.resizer = resizer;
- ensureCapacity(expectedElements);
- }
-
- /**
- * Creates a new deque from elements of another container, appending elements at the end of the
- * deque in the iteration order.
- */
- public CharArrayDeque(CharContainer container) {
- this(container.size());
- addLast(container);
- }
-
- /** {@inheritDoc} */
- @Override
- public void addFirst(char e1) {
- int h = oneLeft(head, buffer.length);
- if (h == tail) {
- ensureBufferSpace(1);
- h = oneLeft(head, buffer.length);
- }
- buffer[head = h] = e1;
- }
-
- /**
- * Vararg-signature method for adding elements at the front of this deque.
- *
- * This method is handy, but costly if used in tight loops (anonymous array passing)
- *
- * @param elements The elements to add.
- */
- public final void addFirst(char... elements) {
- ensureBufferSpace(elements.length);
- for (char k : elements) {
- addFirst(k);
- }
- }
-
- /**
- * Inserts all elements from the given container to the front of this deque.
- *
- * @param container The container to iterate over.
- * @return Returns the number of elements actually added as a result of this call.
- */
- public int addFirst(CharContainer container) {
- int size = container.size();
- ensureBufferSpace(size);
-
- for (CharCursor cursor : container) {
- addFirst(cursor.value);
- }
-
- return size;
- }
-
- /**
- * Inserts all elements from the given iterable to the front of this deque.
- *
- * @param iterable The iterable to iterate over.
- * @return Returns the number of elements actually added as a result of this call.
- */
- public int addFirst(Iterable extends CharCursor> iterable) {
- int size = 0;
- for (CharCursor cursor : iterable) {
- addFirst(cursor.value);
- size++;
- }
- return size;
- }
-
- /** {@inheritDoc} */
- @Override
- public void addLast(char e1) {
- int t = oneRight(tail, buffer.length);
- if (head == t) {
- ensureBufferSpace(1);
- t = oneRight(tail, buffer.length);
- }
- buffer[tail] = e1;
- tail = t;
- }
-
- /**
- * Vararg-signature method for adding elements at the end of this deque.
- *
- * This method is handy, but costly if used in tight loops (anonymous array passing)
- *
- * @param elements The elements to iterate over.
- */
- public final void addLast(char... elements) {
- ensureBufferSpace(1);
- for (char k : elements) {
- addLast(k);
- }
- }
-
- /**
- * Inserts all elements from the given container to the end of this deque.
- *
- * @param container The container to iterate over.
- * @return Returns the number of elements actually added as a result of this call.
- */
- public int addLast(CharContainer container) {
- int size = container.size();
- ensureBufferSpace(size);
-
- for (CharCursor cursor : container) {
- addLast(cursor.value);
- }
-
- return size;
- }
-
- /**
- * Inserts all elements from the given iterable to the end of this deque.
- *
- * @param iterable The iterable to iterate over.
- * @return Returns the number of elements actually added as a result of this call.
- */
- public int addLast(Iterable extends CharCursor> iterable) {
- int size = 0;
- for (CharCursor cursor : iterable) {
- addLast(cursor.value);
- size++;
- }
- return size;
- }
-
- /** {@inheritDoc} */
- @Override
- public char removeFirst() {
- assert size() > 0 : "The deque is empty.";
-
- final char result = buffer[head];
- buffer[head] = ((char) 0);
- head = oneRight(head, buffer.length);
- return result;
- }
-
- /** {@inheritDoc} */
- @Override
- public char removeLast() {
- assert size() > 0 : "The deque is empty.";
-
- tail = oneLeft(tail, buffer.length);
- final char result = buffer[tail];
- buffer[tail] = ((char) 0);
- return result;
- }
-
- /** {@inheritDoc} */
- @Override
- public char getFirst() {
- assert size() > 0 : "The deque is empty.";
-
- return buffer[head];
- }
-
- /** {@inheritDoc} */
- @Override
- public char getLast() {
- assert size() > 0 : "The deque is empty.";
-
- return buffer[oneLeft(tail, buffer.length)];
- }
-
- /** {@inheritDoc} */
- @Override
- public int removeFirst(char e1) {
- final int index = bufferIndexOf(e1);
- if (index >= 0) removeAtBufferIndex(index);
- return index;
- }
-
- /**
- * Return the index of the first (counting from head) element equal to The internal array buffers are not released as a result of this call.
- *
- * @see #release()
- */
- @Override
- public void clear() {
- if (head < tail) {
- Arrays.fill(buffer, head, tail, ((char) 0));
- } else {
- Arrays.fill(buffer, 0, tail, ((char) 0));
- Arrays.fill(buffer, head, buffer.length, ((char) 0));
- }
- this.head = tail = 0;
- }
-
- /** Release internal buffers of this deque and reallocate with the default buffer. */
- public void release() {
- this.head = tail = 0;
- buffer = CharArrayList.EMPTY_ARRAY;
- ensureBufferSpace(0);
- }
-
- /**
- * Ensure this container can hold at least the given number of elements without resizing its
- * buffers.
- *
- * @param expectedElements The total number of elements, inclusive.
- */
- @Override
- public void ensureCapacity(int expectedElements) {
- ensureBufferSpace(expectedElements - size());
- }
-
- /**
- * Ensures the internal buffer has enough free slots to store This method is handy, but costly if used in tight loops (anonymous array passing)
- */
- public final void add(char... elements) {
- add(elements, 0, elements.length);
- }
-
- /** Adds all elements from another container. */
- public int addAll(CharContainer container) {
- final int size = container.size();
- ensureBufferSpace(size);
-
- for (CharCursor cursor : container) {
- add(cursor.value);
- }
-
- return size;
- }
-
- /** Adds all elements from another iterable. */
- public int addAll(Iterable extends CharCursor> iterable) {
- int size = 0;
- for (CharCursor cursor : iterable) {
- add(cursor.value);
- size++;
- }
- return size;
- }
-
- /** {@inheritDoc} */
- @Override
- public void insert(int index, char e1) {
- assert (index >= 0 && index <= size())
- : "Index " + index + " out of bounds [" + 0 + ", " + size() + "].";
-
- ensureBufferSpace(1);
- System.arraycopy(buffer, index, buffer, index + 1, elementsCount - index);
- buffer[index] = e1;
- elementsCount++;
- }
-
- /** {@inheritDoc} */
- @Override
- public char get(int index) {
- assert (index >= 0 && index < size())
- : "Index " + index + " out of bounds [" + 0 + ", " + size() + ").";
-
- return buffer[index];
- }
-
- /** {@inheritDoc} */
- @Override
- public char set(int index, char e1) {
- assert (index >= 0 && index < size())
- : "Index " + index + " out of bounds [" + 0 + ", " + size() + ").";
-
- final char v = buffer[index];
- buffer[index] = e1;
- return v;
- }
-
- /** {@inheritDoc} */
- @Override
- public char removeAt(int index) {
- assert (index >= 0 && index < size())
- : "Index " + index + " out of bounds [" + 0 + ", " + size() + ").";
-
- final char v = buffer[index];
- System.arraycopy(buffer, index + 1, buffer, index, --elementsCount - index);
-
- return v;
- }
-
- /** {@inheritDoc} */
- @Override
- public char removeLast() {
- assert elementsCount > 0;
-
- final char v = buffer[--elementsCount];
-
- return v;
- }
-
- /** {@inheritDoc} */
- @Override
- public void removeRange(int fromIndex, int toIndex) {
- assert (fromIndex >= 0 && fromIndex <= size())
- : "Index " + fromIndex + " out of bounds [" + 0 + ", " + size() + ").";
- assert (toIndex >= 0 && toIndex <= size())
- : "Index " + toIndex + " out of bounds [" + 0 + ", " + size() + "].";
- assert fromIndex <= toIndex : "fromIndex must be <= toIndex: " + fromIndex + ", " + toIndex;
-
- System.arraycopy(buffer, toIndex, buffer, fromIndex, elementsCount - toIndex);
- final int count = toIndex - fromIndex;
- elementsCount -= count;
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean removeElement(char e1) {
- return removeFirst(e1) != -1;
- }
-
- /** {@inheritDoc} */
- @Override
- public int removeFirst(char e1) {
- final int index = indexOf(e1);
- if (index >= 0) removeAt(index);
- return index;
- }
-
- /** {@inheritDoc} */
- @Override
- public int removeLast(char e1) {
- final int index = lastIndexOf(e1);
- if (index >= 0) removeAt(index);
- return index;
- }
-
- /** {@inheritDoc} */
- @Override
- public int removeAll(char e1) {
- int to = 0;
- for (int from = 0; from < elementsCount; from++) {
- if (((e1) == (buffer[from]))) {
- continue;
- }
- if (to != from) {
- buffer[to] = buffer[from];
- }
- to++;
- }
- final int deleted = elementsCount - to;
- this.elementsCount = to;
-
- return deleted;
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean contains(char e1) {
- return indexOf(e1) >= 0;
- }
-
- /** {@inheritDoc} */
- @Override
- public int indexOf(char e1) {
- for (int i = 0; i < elementsCount; i++) {
- if (((e1) == (buffer[i]))) {
- return i;
- }
- }
-
- return -1;
- }
-
- /** {@inheritDoc} */
- @Override
- public int lastIndexOf(char e1) {
- for (int i = elementsCount - 1; i >= 0; i--) {
- if (((e1) == (buffer[i]))) {
- return i;
- }
- }
-
- return -1;
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean isEmpty() {
- return elementsCount == 0;
- }
-
- /**
- * Ensure this container can hold at least the given number of elements without resizing its
- * buffers.
- *
- * @param expectedElements The total number of elements, inclusive.
- */
- @Override
- public void ensureCapacity(int expectedElements) {
- final int bufferLen = (buffer == null ? 0 : buffer.length);
- if (expectedElements > bufferLen) {
- ensureBufferSpace(expectedElements - size());
- }
- }
-
- /**
- * Ensures the internal buffer has enough free slots to store The returned array is sized to match exactly the number of elements of the stack.
- */
- @Override
- public char[] toArray() {
-
- return Arrays.copyOf(buffer, elementsCount);
- }
-
- /** {@inheritDoc} */
- @Override
- public CharIndexedContainer sort() {
- Arrays.sort(buffer, 0, elementsCount);
- return this;
- }
-
- /** {@inheritDoc} */
- @Override
- public CharIndexedContainer reverse() {
- for (int i = 0, mid = elementsCount >> 1, j = elementsCount - 1; i < mid; i++, j--) {
- char tmp = buffer[i];
- buffer[i] = buffer[j];
- buffer[j] = tmp;
- }
- return this;
- }
-
- /**
- * Clone this object. The returned clone will reuse the same hash function and array resizing
- * strategy.
- */
- @Override
- public CharArrayList clone() {
- try {
-
- final CharArrayList cloned = (CharArrayList) super.clone();
- cloned.buffer = buffer.clone();
- return cloned;
- } catch (CloneNotSupportedException e) {
- throw new RuntimeException(e);
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public int hashCode() {
- int h = 1, max = elementsCount;
- for (int i = 0; i < max; i++) {
- h = 31 * h + BitMixer.mix(this.buffer[i]);
- }
- return h;
- }
-
- /**
- * Returns The The iteration is continued as long as the predicate returns The output from this function should evenly distribute keys across the entire integer range.
- */
- protected int hashKey(char key) {
- assert !((key) == 0); // Handled as a special case (empty slot marker).
- return BitMixer.mixPhi(key);
- }
-
- /**
- * Validate load factor range and return it. Override and suppress if you need insane load
- * factors.
- */
- protected double verifyLoadFactor(double loadFactor) {
- checkLoadFactor(loadFactor, MIN_LOAD_FACTOR, MAX_LOAD_FACTOR);
- return loadFactor;
- }
-
- /** Rehash from old buffers to new buffers. */
- protected void rehash(char[] fromKeys, byte[] fromValues) {
- assert fromKeys.length == fromValues.length
- && HashContainers.checkPowerOfTwo(fromKeys.length - 1);
-
- // Rehash all stored key/value pairs into the new buffers.
- final char[] keys = this.keys;
- final byte[] values = this.values;
- final int mask = this.mask;
- char existing;
-
- // Copy the zero element's slot, then rehash everything else.
- int from = fromKeys.length - 1;
- keys[keys.length - 1] = fromKeys[from];
- values[values.length - 1] = fromValues[from];
- while (--from >= 0) {
- if (!((existing = fromKeys[from]) == 0)) {
- int slot = hashKey(existing) & mask;
- while (!((keys[slot]) == 0)) {
- slot = (slot + 1) & mask;
- }
- keys[slot] = existing;
- values[slot] = fromValues[from];
- }
- }
- }
-
- /**
- * Allocate new internal buffers. This method attempts to allocate and assign internal buffers
- * atomically (either allocations succeed or not).
- */
- protected void allocateBuffers(int arraySize) {
- assert Integer.bitCount(arraySize) == 1;
-
- // Ensure no change is done if we hit an OOM.
- char[] prevKeys = this.keys;
- byte[] prevValues = this.values;
- try {
- int emptyElementSlot = 1;
- this.keys = (new char[arraySize + emptyElementSlot]);
- this.values = (new byte[arraySize + emptyElementSlot]);
- } catch (OutOfMemoryError e) {
- this.keys = prevKeys;
- this.values = prevValues;
- throw new BufferAllocationException(
- "Not enough memory to allocate buffers for rehashing: %,d -> %,d",
- e, this.mask + 1, arraySize);
- }
-
- this.resizeAt = expandAtCount(arraySize, loadFactor);
- this.mask = arraySize - 1;
- }
-
- /**
- * This method is invoked when there is a new key/ value pair to be inserted into the buffers but
- * there is not enough empty slots to do so.
- *
- * New buffers are allocated. If this succeeds, we know we can proceed with rehashing so we
- * assign the pending element to the previous buffer (possibly violating the invariant of having
- * at least one empty slot) and rehash all keys, substituting new buffers at the end.
- */
- protected void allocateThenInsertThenRehash(int slot, char pendingKey, byte pendingValue) {
- assert assigned == resizeAt && ((keys[slot]) == 0) && !((pendingKey) == 0);
-
- // Try to allocate new buffers first. If we OOM, we leave in a consistent state.
- final char[] prevKeys = this.keys;
- final byte[] prevValues = this.values;
- allocateBuffers(nextBufferSize(mask + 1, size(), loadFactor));
- assert this.keys.length > prevKeys.length;
-
- // We have succeeded at allocating new data so insert the pending key/value at
- // the free slot in the old arrays before rehashing.
- prevKeys[slot] = pendingKey;
- prevValues[slot] = pendingValue;
-
- // Rehash old keys, including the pending key.
- rehash(prevKeys, prevValues);
- }
-
- /**
- * Shift all the slot-conflicting keys and values allocated to (and including) The semantics of "indexes" are not strictly defined. Indexes may (and typically won't be)
- * contiguous.
- *
- * The index is valid only between map modifications (it will not be affected by read-only
- * operations like iteration or value retrievals).
- *
- * @see #indexExists
- * @see #indexGet
- * @see #indexInsert
- * @see #indexReplace
- * @param key The key to locate in the map.
- * @return A non-negative value of the logical "index" of the key in the map or a negative value
- * if the key did not exist.
- */
- public int indexOf(char key);
-
- /**
- * @see #indexOf
- * @param index The index of a given key, as returned from {@link #indexOf}.
- * @return Returns The The iteration is continued as long as the predicate returns The output from this function should evenly distribute keys across the entire integer range.
- */
- protected int hashKey(char key) {
- assert !((key) == 0); // Handled as a special case (empty slot marker).
- return BitMixer.mixPhi(key);
- }
-
- /**
- * Validate load factor range and return it. Override and suppress if you need insane load
- * factors.
- */
- protected double verifyLoadFactor(double loadFactor) {
- checkLoadFactor(loadFactor, MIN_LOAD_FACTOR, MAX_LOAD_FACTOR);
- return loadFactor;
- }
-
- /** Rehash from old buffers to new buffers. */
- protected void rehash(char[] fromKeys, char[] fromValues) {
- assert fromKeys.length == fromValues.length
- && HashContainers.checkPowerOfTwo(fromKeys.length - 1);
-
- // Rehash all stored key/value pairs into the new buffers.
- final char[] keys = this.keys;
- final char[] values = this.values;
- final int mask = this.mask;
- char existing;
-
- // Copy the zero element's slot, then rehash everything else.
- int from = fromKeys.length - 1;
- keys[keys.length - 1] = fromKeys[from];
- values[values.length - 1] = fromValues[from];
- while (--from >= 0) {
- if (!((existing = fromKeys[from]) == 0)) {
- int slot = hashKey(existing) & mask;
- while (!((keys[slot]) == 0)) {
- slot = (slot + 1) & mask;
- }
- keys[slot] = existing;
- values[slot] = fromValues[from];
- }
- }
- }
-
- /**
- * Allocate new internal buffers. This method attempts to allocate and assign internal buffers
- * atomically (either allocations succeed or not).
- */
- protected void allocateBuffers(int arraySize) {
- assert Integer.bitCount(arraySize) == 1;
-
- // Ensure no change is done if we hit an OOM.
- char[] prevKeys = this.keys;
- char[] prevValues = this.values;
- try {
- int emptyElementSlot = 1;
- this.keys = (new char[arraySize + emptyElementSlot]);
- this.values = (new char[arraySize + emptyElementSlot]);
- } catch (OutOfMemoryError e) {
- this.keys = prevKeys;
- this.values = prevValues;
- throw new BufferAllocationException(
- "Not enough memory to allocate buffers for rehashing: %,d -> %,d",
- e, this.mask + 1, arraySize);
- }
-
- this.resizeAt = expandAtCount(arraySize, loadFactor);
- this.mask = arraySize - 1;
- }
-
- /**
- * This method is invoked when there is a new key/ value pair to be inserted into the buffers but
- * there is not enough empty slots to do so.
- *
- * New buffers are allocated. If this succeeds, we know we can proceed with rehashing so we
- * assign the pending element to the previous buffer (possibly violating the invariant of having
- * at least one empty slot) and rehash all keys, substituting new buffers at the end.
- */
- protected void allocateThenInsertThenRehash(int slot, char pendingKey, char pendingValue) {
- assert assigned == resizeAt && ((keys[slot]) == 0) && !((pendingKey) == 0);
-
- // Try to allocate new buffers first. If we OOM, we leave in a consistent state.
- final char[] prevKeys = this.keys;
- final char[] prevValues = this.values;
- allocateBuffers(nextBufferSize(mask + 1, size(), loadFactor));
- assert this.keys.length > prevKeys.length;
-
- // We have succeeded at allocating new data so insert the pending key/value at
- // the free slot in the old arrays before rehashing.
- prevKeys[slot] = pendingKey;
- prevValues[slot] = pendingValue;
-
- // Rehash old keys, including the pending key.
- rehash(prevKeys, prevValues);
- }
-
- /**
- * Shift all the slot-conflicting keys and values allocated to (and including) The semantics of "indexes" are not strictly defined. Indexes may (and typically won't be)
- * contiguous.
- *
- * The index is valid only between map modifications (it will not be affected by read-only
- * operations like iteration or value retrievals).
- *
- * @see #indexExists
- * @see #indexGet
- * @see #indexInsert
- * @see #indexReplace
- * @param key The key to locate in the map.
- * @return A non-negative value of the logical "index" of the key in the map or a negative value
- * if the key did not exist.
- */
- public int indexOf(char key);
-
- /**
- * @see #indexOf
- * @param index The index of a given key, as returned from {@link #indexOf}.
- * @return Returns The iterator is implemented as a cursor and it returns the same cursor instance on
- * every call to {@link Iterator#next()} (to avoid boxing of primitive types). To read the current
- * list's value (or index in the list) use the cursor's public fields. An example is shown below.
- *
- * The returned array is always a copy, regardless of the storage used by the container.
- */
- public char[] toArray();
-
- /**
- * Applies a The The iteration is continued as long as the predicate returns The output from this function should evenly distribute keys across the entire integer range.
- */
- protected int hashKey(char key) {
- assert !((key) == 0); // Handled as a special case (empty slot marker).
- return BitMixer.mixPhi(key);
- }
-
- /**
- * Validate load factor range and return it. Override and suppress if you need insane load
- * factors.
- */
- protected double verifyLoadFactor(double loadFactor) {
- checkLoadFactor(loadFactor, MIN_LOAD_FACTOR, MAX_LOAD_FACTOR);
- return loadFactor;
- }
-
- /** Rehash from old buffers to new buffers. */
- protected void rehash(char[] fromKeys, double[] fromValues) {
- assert fromKeys.length == fromValues.length
- && HashContainers.checkPowerOfTwo(fromKeys.length - 1);
-
- // Rehash all stored key/value pairs into the new buffers.
- final char[] keys = this.keys;
- final double[] values = this.values;
- final int mask = this.mask;
- char existing;
-
- // Copy the zero element's slot, then rehash everything else.
- int from = fromKeys.length - 1;
- keys[keys.length - 1] = fromKeys[from];
- values[values.length - 1] = fromValues[from];
- while (--from >= 0) {
- if (!((existing = fromKeys[from]) == 0)) {
- int slot = hashKey(existing) & mask;
- while (!((keys[slot]) == 0)) {
- slot = (slot + 1) & mask;
- }
- keys[slot] = existing;
- values[slot] = fromValues[from];
- }
- }
- }
-
- /**
- * Allocate new internal buffers. This method attempts to allocate and assign internal buffers
- * atomically (either allocations succeed or not).
- */
- protected void allocateBuffers(int arraySize) {
- assert Integer.bitCount(arraySize) == 1;
-
- // Ensure no change is done if we hit an OOM.
- char[] prevKeys = this.keys;
- double[] prevValues = this.values;
- try {
- int emptyElementSlot = 1;
- this.keys = (new char[arraySize + emptyElementSlot]);
- this.values = (new double[arraySize + emptyElementSlot]);
- } catch (OutOfMemoryError e) {
- this.keys = prevKeys;
- this.values = prevValues;
- throw new BufferAllocationException(
- "Not enough memory to allocate buffers for rehashing: %,d -> %,d",
- e, this.mask + 1, arraySize);
- }
-
- this.resizeAt = expandAtCount(arraySize, loadFactor);
- this.mask = arraySize - 1;
- }
-
- /**
- * This method is invoked when there is a new key/ value pair to be inserted into the buffers but
- * there is not enough empty slots to do so.
- *
- * New buffers are allocated. If this succeeds, we know we can proceed with rehashing so we
- * assign the pending element to the previous buffer (possibly violating the invariant of having
- * at least one empty slot) and rehash all keys, substituting new buffers at the end.
- */
- protected void allocateThenInsertThenRehash(int slot, char pendingKey, double pendingValue) {
- assert assigned == resizeAt && ((keys[slot]) == 0) && !((pendingKey) == 0);
-
- // Try to allocate new buffers first. If we OOM, we leave in a consistent state.
- final char[] prevKeys = this.keys;
- final double[] prevValues = this.values;
- allocateBuffers(nextBufferSize(mask + 1, size(), loadFactor));
- assert this.keys.length > prevKeys.length;
-
- // We have succeeded at allocating new data so insert the pending key/value at
- // the free slot in the old arrays before rehashing.
- prevKeys[slot] = pendingKey;
- prevValues[slot] = pendingValue;
-
- // Rehash old keys, including the pending key.
- rehash(prevKeys, prevValues);
- }
-
- /**
- * Shift all the slot-conflicting keys and values allocated to (and including) The semantics of "indexes" are not strictly defined. Indexes may (and typically won't be)
- * contiguous.
- *
- * The index is valid only between map modifications (it will not be affected by read-only
- * operations like iteration or value retrievals).
- *
- * @see #indexExists
- * @see #indexGet
- * @see #indexInsert
- * @see #indexReplace
- * @param key The key to locate in the map.
- * @return A non-negative value of the logical "index" of the key in the map or a negative value
- * if the key did not exist.
- */
- public int indexOf(char key);
-
- /**
- * @see #indexOf
- * @param index The index of a given key, as returned from {@link #indexOf}.
- * @return Returns The The iteration is continued as long as the predicate returns The output from this function should evenly distribute keys across the entire integer range.
- */
- protected int hashKey(char key) {
- assert !((key) == 0); // Handled as a special case (empty slot marker).
- return BitMixer.mixPhi(key);
- }
-
- /**
- * Validate load factor range and return it. Override and suppress if you need insane load
- * factors.
- */
- protected double verifyLoadFactor(double loadFactor) {
- checkLoadFactor(loadFactor, MIN_LOAD_FACTOR, MAX_LOAD_FACTOR);
- return loadFactor;
- }
-
- /** Rehash from old buffers to new buffers. */
- protected void rehash(char[] fromKeys, float[] fromValues) {
- assert fromKeys.length == fromValues.length
- && HashContainers.checkPowerOfTwo(fromKeys.length - 1);
-
- // Rehash all stored key/value pairs into the new buffers.
- final char[] keys = this.keys;
- final float[] values = this.values;
- final int mask = this.mask;
- char existing;
-
- // Copy the zero element's slot, then rehash everything else.
- int from = fromKeys.length - 1;
- keys[keys.length - 1] = fromKeys[from];
- values[values.length - 1] = fromValues[from];
- while (--from >= 0) {
- if (!((existing = fromKeys[from]) == 0)) {
- int slot = hashKey(existing) & mask;
- while (!((keys[slot]) == 0)) {
- slot = (slot + 1) & mask;
- }
- keys[slot] = existing;
- values[slot] = fromValues[from];
- }
- }
- }
-
- /**
- * Allocate new internal buffers. This method attempts to allocate and assign internal buffers
- * atomically (either allocations succeed or not).
- */
- protected void allocateBuffers(int arraySize) {
- assert Integer.bitCount(arraySize) == 1;
-
- // Ensure no change is done if we hit an OOM.
- char[] prevKeys = this.keys;
- float[] prevValues = this.values;
- try {
- int emptyElementSlot = 1;
- this.keys = (new char[arraySize + emptyElementSlot]);
- this.values = (new float[arraySize + emptyElementSlot]);
- } catch (OutOfMemoryError e) {
- this.keys = prevKeys;
- this.values = prevValues;
- throw new BufferAllocationException(
- "Not enough memory to allocate buffers for rehashing: %,d -> %,d",
- e, this.mask + 1, arraySize);
- }
-
- this.resizeAt = expandAtCount(arraySize, loadFactor);
- this.mask = arraySize - 1;
- }
-
- /**
- * This method is invoked when there is a new key/ value pair to be inserted into the buffers but
- * there is not enough empty slots to do so.
- *
- * New buffers are allocated. If this succeeds, we know we can proceed with rehashing so we
- * assign the pending element to the previous buffer (possibly violating the invariant of having
- * at least one empty slot) and rehash all keys, substituting new buffers at the end.
- */
- protected void allocateThenInsertThenRehash(int slot, char pendingKey, float pendingValue) {
- assert assigned == resizeAt && ((keys[slot]) == 0) && !((pendingKey) == 0);
-
- // Try to allocate new buffers first. If we OOM, we leave in a consistent state.
- final char[] prevKeys = this.keys;
- final float[] prevValues = this.values;
- allocateBuffers(nextBufferSize(mask + 1, size(), loadFactor));
- assert this.keys.length > prevKeys.length;
-
- // We have succeeded at allocating new data so insert the pending key/value at
- // the free slot in the old arrays before rehashing.
- prevKeys[slot] = pendingKey;
- prevValues[slot] = pendingValue;
-
- // Rehash old keys, including the pending key.
- rehash(prevKeys, prevValues);
- }
-
- /**
- * Shift all the slot-conflicting keys and values allocated to (and including) The semantics of "indexes" are not strictly defined. Indexes may (and typically won't be)
- * contiguous.
- *
- * The index is valid only between map modifications (it will not be affected by read-only
- * operations like iteration or value retrievals).
- *
- * @see #indexExists
- * @see #indexGet
- * @see #indexInsert
- * @see #indexReplace
- * @param key The key to locate in the map.
- * @return A non-negative value of the logical "index" of the key in the map or a negative value
- * if the key did not exist.
- */
- public int indexOf(char key);
-
- /**
- * @see #indexOf
- * @param index The index of a given key, as returned from {@link #indexOf}.
- * @return Returns The output from this function should evenly distribute keys across the entire integer range.
- */
- protected int hashKey(char key) {
- assert !((key) == 0); // Handled as a special case (empty slot marker).
- return BitMixer.mixPhi(key);
- }
-
- /**
- * Returns a logical "index" of a given key that can be used to speed up follow-up logic in
- * certain scenarios (conditional logic).
- *
- * The semantics of "indexes" are not strictly defined. Indexes may (and typically won't be)
- * contiguous.
- *
- * The index is valid only between modifications (it will not be affected by read-only
- * operations).
- *
- * @see #indexExists
- * @see #indexGet
- * @see #indexInsert
- * @see #indexReplace
- * @param key The key to locate in the set.
- * @return A non-negative value of the logical "index" of the key in the set or a negative value
- * if the key did not exist.
- */
- public int indexOf(char key) {
- final int mask = this.mask;
- if (((key) == 0)) {
- return hasEmptyKey ? mask + 1 : ~(mask + 1);
- } else {
- final char[] keys = this.keys;
- int slot = hashKey(key) & mask;
-
- char existing;
- while (!((existing = keys[slot]) == 0)) {
- if (((key) == (existing))) {
- return slot;
- }
- slot = (slot + 1) & mask;
- }
-
- return ~slot;
- }
- }
-
- /**
- * @see #indexOf
- * @param index The index of a given key, as returned from {@link #indexOf}.
- * @return Returns New buffers are allocated. If this succeeds, we know we can proceed with rehashing so we
- * assign the pending element to the previous buffer (possibly violating the invariant of having
- * at least one empty slot) and rehash all keys, substituting new buffers at the end.
- */
- protected void allocateThenInsertThenRehash(int slot, char pendingKey) {
- assert assigned == resizeAt && ((keys[slot]) == 0) && !((pendingKey) == 0);
-
- // Try to allocate new buffers first. If we OOM, we leave in a consistent state.
- final char[] prevKeys = this.keys;
- allocateBuffers(nextBufferSize(mask + 1, size(), loadFactor));
- assert this.keys.length > prevKeys.length;
-
- // We have succeeded at allocating new data so insert the pending key/value at
- // the free slot in the old arrays before rehashing.
- prevKeys[slot] = pendingKey;
-
- // Rehash old keys, including the pending key.
- rehash(prevKeys);
- }
-
- /** Shift all the slot-conflicting keys allocated to (and including) The The iteration is continued as long as the predicate returns The output from this function should evenly distribute keys across the entire integer range.
- */
- protected int hashKey(char key) {
- assert !((key) == 0); // Handled as a special case (empty slot marker).
- return BitMixer.mixPhi(key);
- }
-
- /**
- * Validate load factor range and return it. Override and suppress if you need insane load
- * factors.
- */
- protected double verifyLoadFactor(double loadFactor) {
- checkLoadFactor(loadFactor, MIN_LOAD_FACTOR, MAX_LOAD_FACTOR);
- return loadFactor;
- }
-
- /** Rehash from old buffers to new buffers. */
- protected void rehash(char[] fromKeys, int[] fromValues) {
- assert fromKeys.length == fromValues.length
- && HashContainers.checkPowerOfTwo(fromKeys.length - 1);
-
- // Rehash all stored key/value pairs into the new buffers.
- final char[] keys = this.keys;
- final int[] values = this.values;
- final int mask = this.mask;
- char existing;
-
- // Copy the zero element's slot, then rehash everything else.
- int from = fromKeys.length - 1;
- keys[keys.length - 1] = fromKeys[from];
- values[values.length - 1] = fromValues[from];
- while (--from >= 0) {
- if (!((existing = fromKeys[from]) == 0)) {
- int slot = hashKey(existing) & mask;
- while (!((keys[slot]) == 0)) {
- slot = (slot + 1) & mask;
- }
- keys[slot] = existing;
- values[slot] = fromValues[from];
- }
- }
- }
-
- /**
- * Allocate new internal buffers. This method attempts to allocate and assign internal buffers
- * atomically (either allocations succeed or not).
- */
- protected void allocateBuffers(int arraySize) {
- assert Integer.bitCount(arraySize) == 1;
-
- // Ensure no change is done if we hit an OOM.
- char[] prevKeys = this.keys;
- int[] prevValues = this.values;
- try {
- int emptyElementSlot = 1;
- this.keys = (new char[arraySize + emptyElementSlot]);
- this.values = (new int[arraySize + emptyElementSlot]);
- } catch (OutOfMemoryError e) {
- this.keys = prevKeys;
- this.values = prevValues;
- throw new BufferAllocationException(
- "Not enough memory to allocate buffers for rehashing: %,d -> %,d",
- e, this.mask + 1, arraySize);
- }
-
- this.resizeAt = expandAtCount(arraySize, loadFactor);
- this.mask = arraySize - 1;
- }
-
- /**
- * This method is invoked when there is a new key/ value pair to be inserted into the buffers but
- * there is not enough empty slots to do so.
- *
- * New buffers are allocated. If this succeeds, we know we can proceed with rehashing so we
- * assign the pending element to the previous buffer (possibly violating the invariant of having
- * at least one empty slot) and rehash all keys, substituting new buffers at the end.
- */
- protected void allocateThenInsertThenRehash(int slot, char pendingKey, int pendingValue) {
- assert assigned == resizeAt && ((keys[slot]) == 0) && !((pendingKey) == 0);
-
- // Try to allocate new buffers first. If we OOM, we leave in a consistent state.
- final char[] prevKeys = this.keys;
- final int[] prevValues = this.values;
- allocateBuffers(nextBufferSize(mask + 1, size(), loadFactor));
- assert this.keys.length > prevKeys.length;
-
- // We have succeeded at allocating new data so insert the pending key/value at
- // the free slot in the old arrays before rehashing.
- prevKeys[slot] = pendingKey;
- prevValues[slot] = pendingValue;
-
- // Rehash old keys, including the pending key.
- rehash(prevKeys, prevValues);
- }
-
- /**
- * Shift all the slot-conflicting keys and values allocated to (and including) The semantics of "indexes" are not strictly defined. Indexes may (and typically won't be)
- * contiguous.
- *
- * The index is valid only between map modifications (it will not be affected by read-only
- * operations like iteration or value retrievals).
- *
- * @see #indexExists
- * @see #indexGet
- * @see #indexInsert
- * @see #indexReplace
- * @param key The key to locate in the map.
- * @return A non-negative value of the logical "index" of the key in the map or a negative value
- * if the key did not exist.
- */
- public int indexOf(char key);
-
- /**
- * @see #indexOf
- * @param index The index of a given key, as returned from {@link #indexOf}.
- * @return Returns The The iteration is continued as long as the predicate returns The output from this function should evenly distribute keys across the entire integer range.
- */
- protected int hashKey(char key) {
- assert !((key) == 0); // Handled as a special case (empty slot marker).
- return BitMixer.mixPhi(key);
- }
-
- /**
- * Validate load factor range and return it. Override and suppress if you need insane load
- * factors.
- */
- protected double verifyLoadFactor(double loadFactor) {
- checkLoadFactor(loadFactor, MIN_LOAD_FACTOR, MAX_LOAD_FACTOR);
- return loadFactor;
- }
-
- /** Rehash from old buffers to new buffers. */
- protected void rehash(char[] fromKeys, long[] fromValues) {
- assert fromKeys.length == fromValues.length
- && HashContainers.checkPowerOfTwo(fromKeys.length - 1);
-
- // Rehash all stored key/value pairs into the new buffers.
- final char[] keys = this.keys;
- final long[] values = this.values;
- final int mask = this.mask;
- char existing;
-
- // Copy the zero element's slot, then rehash everything else.
- int from = fromKeys.length - 1;
- keys[keys.length - 1] = fromKeys[from];
- values[values.length - 1] = fromValues[from];
- while (--from >= 0) {
- if (!((existing = fromKeys[from]) == 0)) {
- int slot = hashKey(existing) & mask;
- while (!((keys[slot]) == 0)) {
- slot = (slot + 1) & mask;
- }
- keys[slot] = existing;
- values[slot] = fromValues[from];
- }
- }
- }
-
- /**
- * Allocate new internal buffers. This method attempts to allocate and assign internal buffers
- * atomically (either allocations succeed or not).
- */
- protected void allocateBuffers(int arraySize) {
- assert Integer.bitCount(arraySize) == 1;
-
- // Ensure no change is done if we hit an OOM.
- char[] prevKeys = this.keys;
- long[] prevValues = this.values;
- try {
- int emptyElementSlot = 1;
- this.keys = (new char[arraySize + emptyElementSlot]);
- this.values = (new long[arraySize + emptyElementSlot]);
- } catch (OutOfMemoryError e) {
- this.keys = prevKeys;
- this.values = prevValues;
- throw new BufferAllocationException(
- "Not enough memory to allocate buffers for rehashing: %,d -> %,d",
- e, this.mask + 1, arraySize);
- }
-
- this.resizeAt = expandAtCount(arraySize, loadFactor);
- this.mask = arraySize - 1;
- }
-
- /**
- * This method is invoked when there is a new key/ value pair to be inserted into the buffers but
- * there is not enough empty slots to do so.
- *
- * New buffers are allocated. If this succeeds, we know we can proceed with rehashing so we
- * assign the pending element to the previous buffer (possibly violating the invariant of having
- * at least one empty slot) and rehash all keys, substituting new buffers at the end.
- */
- protected void allocateThenInsertThenRehash(int slot, char pendingKey, long pendingValue) {
- assert assigned == resizeAt && ((keys[slot]) == 0) && !((pendingKey) == 0);
-
- // Try to allocate new buffers first. If we OOM, we leave in a consistent state.
- final char[] prevKeys = this.keys;
- final long[] prevValues = this.values;
- allocateBuffers(nextBufferSize(mask + 1, size(), loadFactor));
- assert this.keys.length > prevKeys.length;
-
- // We have succeeded at allocating new data so insert the pending key/value at
- // the free slot in the old arrays before rehashing.
- prevKeys[slot] = pendingKey;
- prevValues[slot] = pendingValue;
-
- // Rehash old keys, including the pending key.
- rehash(prevKeys, prevValues);
- }
-
- /**
- * Shift all the slot-conflicting keys and values allocated to (and including) The semantics of "indexes" are not strictly defined. Indexes may (and typically won't be)
- * contiguous.
- *
- * The index is valid only between map modifications (it will not be affected by read-only
- * operations like iteration or value retrievals).
- *
- * @see #indexExists
- * @see #indexGet
- * @see #indexInsert
- * @see #indexReplace
- * @param key The key to locate in the map.
- * @return A non-negative value of the logical "index" of the key in the map or a negative value
- * if the key did not exist.
- */
- public int indexOf(char key);
-
- /**
- * @see #indexOf
- * @param index The index of a given key, as returned from {@link #indexOf}.
- * @return Returns The The iteration is continued as long as the predicate returns The output from this function should evenly distribute keys across the entire integer range.
- */
- protected int hashKey(char key) {
- assert !((key) == 0); // Handled as a special case (empty slot marker).
- return BitMixer.mixPhi(key);
- }
-
- /**
- * Validate load factor range and return it. Override and suppress if you need insane load
- * factors.
- */
- protected double verifyLoadFactor(double loadFactor) {
- checkLoadFactor(loadFactor, MIN_LOAD_FACTOR, MAX_LOAD_FACTOR);
- return loadFactor;
- }
-
- /** Rehash from old buffers to new buffers. */
- protected void rehash(char[] fromKeys, VType[] fromValues) {
- assert fromKeys.length == fromValues.length
- && HashContainers.checkPowerOfTwo(fromKeys.length - 1);
-
- // Rehash all stored key/value pairs into the new buffers.
- final char[] keys = this.keys;
- final VType[] values = (VType[]) this.values;
- final int mask = this.mask;
- char existing;
-
- // Copy the zero element's slot, then rehash everything else.
- int from = fromKeys.length - 1;
- keys[keys.length - 1] = fromKeys[from];
- values[values.length - 1] = fromValues[from];
- while (--from >= 0) {
- if (!((existing = fromKeys[from]) == 0)) {
- int slot = hashKey(existing) & mask;
- while (!((keys[slot]) == 0)) {
- slot = (slot + 1) & mask;
- }
- keys[slot] = existing;
- values[slot] = fromValues[from];
- }
- }
- }
-
- /**
- * Allocate new internal buffers. This method attempts to allocate and assign internal buffers
- * atomically (either allocations succeed or not).
- */
- protected void allocateBuffers(int arraySize) {
- assert Integer.bitCount(arraySize) == 1;
-
- // Ensure no change is done if we hit an OOM.
- char[] prevKeys = this.keys;
- VType[] prevValues = (VType[]) this.values;
- try {
- int emptyElementSlot = 1;
- this.keys = (new char[arraySize + emptyElementSlot]);
- this.values = ((VType[]) new Object[arraySize + emptyElementSlot]);
- } catch (OutOfMemoryError e) {
- this.keys = prevKeys;
- this.values = prevValues;
- throw new BufferAllocationException(
- "Not enough memory to allocate buffers for rehashing: %,d -> %,d",
- e, this.mask + 1, arraySize);
- }
-
- this.resizeAt = expandAtCount(arraySize, loadFactor);
- this.mask = arraySize - 1;
- }
-
- /**
- * This method is invoked when there is a new key/ value pair to be inserted into the buffers but
- * there is not enough empty slots to do so.
- *
- * New buffers are allocated. If this succeeds, we know we can proceed with rehashing so we
- * assign the pending element to the previous buffer (possibly violating the invariant of having
- * at least one empty slot) and rehash all keys, substituting new buffers at the end.
- */
- protected void allocateThenInsertThenRehash(int slot, char pendingKey, VType pendingValue) {
- assert assigned == resizeAt && ((keys[slot]) == 0) && !((pendingKey) == 0);
-
- // Try to allocate new buffers first. If we OOM, we leave in a consistent state.
- final char[] prevKeys = this.keys;
- final VType[] prevValues = (VType[]) this.values;
- allocateBuffers(nextBufferSize(mask + 1, size(), loadFactor));
- assert this.keys.length > prevKeys.length;
-
- // We have succeeded at allocating new data so insert the pending key/value at
- // the free slot in the old arrays before rehashing.
- prevKeys[slot] = pendingKey;
- prevValues[slot] = pendingValue;
-
- // Rehash old keys, including the pending key.
- rehash(prevKeys, prevValues);
- }
-
- /**
- * Shift all the slot-conflicting keys and values allocated to (and including) The semantics of "indexes" are not strictly defined. Indexes may (and typically won't be)
- * contiguous.
- *
- * The index is valid only between map modifications (it will not be affected by read-only
- * operations like iteration or value retrievals).
- *
- * @see #indexExists
- * @see #indexGet
- * @see #indexInsert
- * @see #indexReplace
- * @param key The key to locate in the map.
- * @return A non-negative value of the logical "index" of the key in the map or a negative value
- * if the key did not exist.
- */
- public int indexOf(char key);
-
- /**
- * @see #indexOf
- * @param index The index of a given key, as returned from {@link #indexOf}.
- * @return Returns The The iteration is continued as long as the predicate returns
- * minGrow = 1
- * maxGrow = Integer.MAX_VALUE (unbounded)
- * growRatio = 1.5f
- *
- */
-public final class BoundedProportionalArraySizingStrategy implements ArraySizingStrategy {
-
- /** Instance of {@link BoundedProportionalArraySizingStrategy} with default values. */
- public static final BoundedProportionalArraySizingStrategy DEFAULT_INSTANCE =
- new BoundedProportionalArraySizingStrategy();
-
- /**
- * Maximum allocable array length (approximately the largest positive integer decreased by the
- * array's object header).
- */
- public static final int MAX_ARRAY_LENGTH =
- Integer.MAX_VALUE - /* aligned array header + slack */ 32;
-
- /** Minimum grow count. */
- public static final int DEFAULT_MIN_GROW_COUNT = 10;
-
- /** Maximum grow count (unbounded). */
- public static final int DEFAULT_MAX_GROW_COUNT = MAX_ARRAY_LENGTH;
-
- /** Default resize is by half the current buffer's size. */
- public static final float DEFAULT_GROW_RATIO = 1.5f;
-
- /** Minimum number of elements to grow, if limit exceeded. */
- public final int minGrowCount;
-
- /** Maximum number of elements to grow, if limit exceeded. */
- public final int maxGrowCount;
-
- /**
- * The current buffer length is multiplied by this ratio to get the first estimate for the new
- * size. To double the size of the current buffer, for example, set to 2
.
- */
- public final float growRatio;
-
- /** Create the default sizing strategy. */
- public BoundedProportionalArraySizingStrategy() {
- this(DEFAULT_MIN_GROW_COUNT, DEFAULT_MAX_GROW_COUNT, DEFAULT_GROW_RATIO);
- }
-
- /**
- * Create the sizing strategy with custom policies.
- *
- * @param minGrow Minimum number of elements to grow by when expanding.
- * @param maxGrow Maximum number of elements to grow by when expanding.
- * @param ratio The ratio of expansion compared to the previous buffer size.
- */
- public BoundedProportionalArraySizingStrategy(int minGrow, int maxGrow, float ratio) {
- assert minGrow >= 1 : "Min grow must be >= 1.";
- assert maxGrow >= minGrow : "Max grow must be >= min grow.";
- assert ratio >= 1f : "Growth ratio must be >= 1 (was " + ratio + ").";
-
- this.minGrowCount = minGrow;
- this.maxGrowCount = maxGrow;
- this.growRatio = ratio - 1.0f;
- }
-
- /**
- * Grow according to {@link #growRatio}, {@link #minGrowCount} and {@link #maxGrowCount}.
- *
- * @param currentBufferLength The current length of the buffer.
- * @param elementsCount The number of elements stored in the buffer.
- * @param expectedAdditions The number of expected additions to the buffer.
- * @return New buffer size.
- */
- public int grow(int currentBufferLength, int elementsCount, int expectedAdditions) {
- long growBy = (long) ((long) currentBufferLength * growRatio);
- growBy = Math.max(growBy, minGrowCount);
- growBy = Math.min(growBy, maxGrowCount);
- long growTo = Math.min(MAX_ARRAY_LENGTH, growBy + currentBufferLength);
- long newSize = Math.max((long) elementsCount + expectedAdditions, growTo);
-
- if (newSize > MAX_ARRAY_LENGTH) {
- throw new BufferAllocationException(
- "Java array size exceeded (current length: %d, elements: %d, expected additions: %d)",
- currentBufferLength, elementsCount, expectedAdditions);
- }
-
- return (int) newSize;
- }
-
- @Override
- public long ramBytesAllocated() {
- // int: minGrowCount, maxGrowCount
- // float: growRatio
- return RamUsageEstimator.NUM_BYTES_OBJECT_HEADER + Integer.BYTES * 2 + Float.BYTES;
- }
-
- @Override
- public long ramBytesUsed() {
- return ramBytesAllocated();
- }
-}
diff --git a/sources/main/java/com/carrotsearch/hppc/BufferAllocationException.java b/sources/main/java/com/carrotsearch/hppc/BufferAllocationException.java
deleted file mode 100644
index f09ef3c8..00000000
--- a/sources/main/java/com/carrotsearch/hppc/BufferAllocationException.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * HPPC
- *
- * Copyright (C) 2010-2024 Carrot Search s.c. and contributors
- * All rights reserved.
- *
- * Refer to the full license file "LICENSE.txt":
- * https://github.com/carrotsearch/hppc/blob/master/LICENSE.txt
- */
-package com.carrotsearch.hppc;
-
-import java.util.IllegalFormatException;
-import java.util.Locale;
-
-public class BufferAllocationException extends RuntimeException {
- public BufferAllocationException(String message) {
- super(message);
- }
-
- public BufferAllocationException(String message, Object... args) {
- this(message, null, args);
- }
-
- public BufferAllocationException(String message, Throwable t, Object... args) {
- super(formatMessage(message, t, args), t);
- }
-
- private static String formatMessage(String message, Throwable t, Object... args) {
- try {
- return String.format(Locale.ROOT, message, args);
- } catch (IllegalFormatException e) {
- BufferAllocationException substitute =
- new BufferAllocationException(message + " [ILLEGAL FORMAT, ARGS SUPPRESSED]");
- if (t != null) {
- substitute.addSuppressed(t);
- }
- substitute.addSuppressed(e);
- throw substitute;
- }
- }
-}
diff --git a/sources/main/java/com/carrotsearch/hppc/ByteArrayDeque.java b/sources/main/java/com/carrotsearch/hppc/ByteArrayDeque.java
deleted file mode 100644
index b9c809c1..00000000
--- a/sources/main/java/com/carrotsearch/hppc/ByteArrayDeque.java
+++ /dev/null
@@ -1,776 +0,0 @@
-package com.carrotsearch.hppc;
-
-import static com.carrotsearch.hppc.Containers.*;
-
-import com.carrotsearch.hppc.cursors.ByteCursor;
-import com.carrotsearch.hppc.predicates.BytePredicate;
-import com.carrotsearch.hppc.procedures.ByteProcedure;
-import java.util.*;
-
-/** An array-backed {@link ByteDeque}. */
-@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeArrayDeque.java")
-public class ByteArrayDeque extends AbstractByteCollection
- implements ByteDeque, Preallocable, Cloneable, Accountable {
-
- /** Reuse the same strategy instance. */
- private static final BoundedProportionalArraySizingStrategy DEFAULT_SIZING_STRATEGY =
- BoundedProportionalArraySizingStrategy.DEFAULT_INSTANCE;
-
- /** Internal array for storing elements of the deque. */
- public byte[] buffer = ByteArrayList.EMPTY_ARRAY;
-
- /**
- * The index of the element at the head of the deque or an arbitrary number equal to tail if the
- * deque is empty.
- */
- public int head;
-
- /** The index at which the next element would be added to the tail of the deque. */
- public int tail;
-
- /** Buffer resizing strategy. */
- protected final ArraySizingStrategy resizer;
-
- /** New instance with sane defaults. */
- public ByteArrayDeque() {
- this(DEFAULT_EXPECTED_ELEMENTS);
- }
-
- /**
- * New instance with sane defaults.
- *
- * @param expectedElements The expected number of elements guaranteed not to cause buffer
- * expansion (inclusive).
- */
- public ByteArrayDeque(int expectedElements) {
- this(expectedElements, DEFAULT_SIZING_STRATEGY);
- }
-
- /**
- * New instance with sane defaults.
- *
- * @param expectedElements The expected number of elements guaranteed not to cause buffer
- * expansion (inclusive).
- * @param resizer Underlying buffer sizing strategy.
- */
- public ByteArrayDeque(int expectedElements, ArraySizingStrategy resizer) {
- assert resizer != null;
- this.resizer = resizer;
- ensureCapacity(expectedElements);
- }
-
- /**
- * Creates a new deque from elements of another container, appending elements at the end of the
- * deque in the iteration order.
- */
- public ByteArrayDeque(ByteContainer container) {
- this(container.size());
- addLast(container);
- }
-
- /** {@inheritDoc} */
- @Override
- public void addFirst(byte e1) {
- int h = oneLeft(head, buffer.length);
- if (h == tail) {
- ensureBufferSpace(1);
- h = oneLeft(head, buffer.length);
- }
- buffer[head = h] = e1;
- }
-
- /**
- * Vararg-signature method for adding elements at the front of this deque.
- *
- * e1
. The index
- * points to the {@link #buffer} array.
- *
- * @param e1 The element to look for.
- * @return Returns the index of the first element equal to e1
or -1
if
- * not found.
- */
- public int bufferIndexOf(byte e1) {
- final int last = tail;
- final int bufLen = buffer.length;
- for (int i = head; i != last; i = oneRight(i, bufLen)) {
- if (((e1) == (buffer[i]))) {
- return i;
- }
- }
-
- return -1;
- }
-
- /** {@inheritDoc} */
- @Override
- public int removeLast(byte e1) {
- final int index = lastBufferIndexOf(e1);
- if (index >= 0) {
- removeAtBufferIndex(index);
- }
- return index;
- }
-
- /**
- * Return the index of the last (counting from tail) element equal to e1
. The index
- * points to the {@link #buffer} array.
- *
- * @param e1 The element to look for.
- * @return Returns the index of the first element equal to e1
or -1
if
- * not found.
- */
- public int lastBufferIndexOf(byte e1) {
- final int bufLen = buffer.length;
- final int last = oneLeft(head, bufLen);
- for (int i = oneLeft(tail, bufLen); i != last; i = oneLeft(i, bufLen)) {
- if (((e1) == (buffer[i]))) return i;
- }
-
- return -1;
- }
-
- /** {@inheritDoc} */
- @Override
- public int removeAll(byte e1) {
- int removed = 0;
- final int last = tail;
- final int bufLen = buffer.length;
- int from, to;
- for (from = to = head; from != last; from = oneRight(from, bufLen)) {
- if (((e1) == (buffer[from]))) {
- buffer[from] = ((byte) 0);
- removed++;
- continue;
- }
-
- if (to != from) {
- buffer[to] = buffer[from];
- buffer[from] = ((byte) 0);
- }
-
- to = oneRight(to, bufLen);
- }
-
- tail = to;
- return removed;
- }
-
- /**
- * Removes the element at index
in the internal {#link {@link #buffer} array,
- * returning its value.
- *
- * @param index Index of the element to remove. The index must be located between {@link #head}
- * and {@link #tail} in modulo {@link #buffer} arithmetic.
- */
- public void removeAtBufferIndex(int index) {
- assert (head <= tail ? index >= head && index < tail : index >= head || index < tail)
- : "Index out of range (head=" + head + ", tail=" + tail + ", index=" + index + ").";
-
- // Cache fields in locals (hopefully moved to registers).
- final byte[] buffer = this.buffer;
- final int bufLen = buffer.length;
- final int lastIndex = bufLen - 1;
- final int head = this.head;
- final int tail = this.tail;
-
- final int leftChunk = Math.abs(index - head) % bufLen;
- final int rightChunk = Math.abs(tail - index) % bufLen;
-
- if (leftChunk < rightChunk) {
- if (index >= head) {
- System.arraycopy(buffer, head, buffer, head + 1, leftChunk);
- } else {
- System.arraycopy(buffer, 0, buffer, 1, index);
- buffer[0] = buffer[lastIndex];
- System.arraycopy(buffer, head, buffer, head + 1, lastIndex - head);
- }
- buffer[head] = ((byte) 0);
- this.head = oneRight(head, bufLen);
- } else {
- if (index < tail) {
- System.arraycopy(buffer, index + 1, buffer, index, rightChunk);
- } else {
- System.arraycopy(buffer, index + 1, buffer, index, lastIndex - index);
- buffer[lastIndex] = buffer[0];
- System.arraycopy(buffer, 1, buffer, 0, tail);
- }
- buffer[tail] = ((byte) 0);
- this.tail = oneLeft(tail, bufLen);
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean isEmpty() {
- return size() == 0;
- }
-
- /** {@inheritDoc} */
- @Override
- public int size() {
- if (head <= tail) return tail - head;
- else return (tail - head + buffer.length);
- }
-
- /**
- * {@inheritDoc}
- *
- * expectedAdditions
.
- * Increases internal buffer size if needed.
- */
- protected void ensureBufferSpace(int expectedAdditions) {
- final int bufferLen = buffer.length;
- final int elementsCount = size();
-
- if (elementsCount + expectedAdditions >= bufferLen) {
- final int emptySlot = 1; // deque invariant: always an empty slot.
- final int newSize = resizer.grow(bufferLen, elementsCount + emptySlot, expectedAdditions);
- assert newSize >= (elementsCount + expectedAdditions + emptySlot)
- : "Resizer failed to"
- + " return sensible new size: "
- + newSize
- + " <= "
- + (elementsCount + expectedAdditions);
-
- try {
- final byte[] newBuffer = (new byte[newSize]);
- if (bufferLen > 0) {
- toArray(newBuffer);
- tail = elementsCount;
- head = 0;
- }
- this.buffer = newBuffer;
- } catch (OutOfMemoryError e) {
- throw new BufferAllocationException(
- "Not enough memory to allocate new buffers: %,d -> %,d", e, bufferLen, newSize);
- }
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public byte[] toArray() {
-
- final int size = size();
- return toArray((new byte[size]));
- }
-
- /**
- * Copies elements of this deque to an array. The content of the target
array is
- * filled from index 0 (head of the queue) to index size() - 1
(tail of the queue).
- *
- * @param target The target array must be large enough to hold all elements.
- * @return Returns the target argument for chaining.
- */
- public byte[] toArray(byte[] target) {
- assert target.length >= size() : "Target array must be >= " + size();
-
- if (head < tail) {
- // The contents is not wrapped around. Just copy.
- System.arraycopy(buffer, head, target, 0, size());
- } else if (head > tail) {
- // The contents is split. Merge elements from the following indexes:
- // [head...buffer.length - 1][0, tail - 1]
- final int rightCount = buffer.length - head;
- System.arraycopy(buffer, head, target, 0, rightCount);
- System.arraycopy(buffer, 0, target, rightCount, tail);
- }
-
- return target;
- }
-
- /**
- * Clone this object. The returned clone will reuse the same hash function and array resizing
- * strategy.
- */
- @Override
- public ByteArrayDeque clone() {
- try {
-
- ByteArrayDeque cloned = (ByteArrayDeque) super.clone();
- cloned.buffer = buffer.clone();
- return cloned;
- } catch (CloneNotSupportedException e) {
- throw new RuntimeException(e);
- }
- }
-
- /** Move one index to the left, wrapping around buffer. */
- protected static int oneLeft(int index, int modulus) {
- if (index >= 1) {
- return index - 1;
- }
- return modulus - 1;
- }
-
- /** Move one index to the right, wrapping around buffer. */
- protected static int oneRight(int index, int modulus) {
- if (index + 1 == modulus) {
- return 0;
- }
- return index + 1;
- }
-
- @Override
- public long ramBytesAllocated() {
- // int: head, tail
- return RamUsageEstimator.NUM_BYTES_OBJECT_HEADER
- + Integer.BYTES * 2
- + resizer.ramBytesAllocated()
- + RamUsageEstimator.shallowSizeOfArray(buffer);
- }
-
- @Override
- public long ramBytesUsed() {
- // int: head, tail
- return RamUsageEstimator.NUM_BYTES_OBJECT_HEADER
- + Integer.BYTES * 2
- + resizer.ramBytesUsed()
- + RamUsageEstimator.shallowUsedSizeOfArray(buffer, size());
- }
-
- /** An iterator implementation for {@link ObjectArrayDeque#iterator}. */
- private final class ValueIterator extends AbstractIterator
- * for (IntValueCursor c : intDeque) {
- * System.out.println("buffer index=" + c.index + " value=" + c.value);
- * }
- *
- */
- public Iterator
- * for (Iterator<IntCursor> i = intDeque.descendingIterator(); i.hasNext();) {
- * final IntCursor c = i.next();
- * System.out.println("buffer index=" + c.index + " value=" + c.value);
- * }
- *
- */
- public Iteratorprocedure
to a slice of the deque, fromIndex
, inclusive, to
- * toIndex
, exclusive.
- */
- private void forEach(ByteProcedure procedure, int fromIndex, final int toIndex) {
- final byte[] buffer = this.buffer;
- for (int i = fromIndex; i != toIndex; i = oneRight(i, buffer.length)) {
- procedure.apply(buffer[i]);
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public procedure
to all elements of this deque, tail to head. */
- @Override
- public procedure
to a slice of the deque, toIndex
, exclusive, down
- * to fromIndex
, inclusive.
- */
- private void descendingForEach(ByteProcedure procedure, int fromIndex, final int toIndex) {
- if (fromIndex == toIndex) return;
-
- final byte[] buffer = this.buffer;
- int i = toIndex;
- do {
- i = oneLeft(i, buffer.length);
- procedure.apply(buffer[i]);
- } while (i != fromIndex);
- }
-
- /** {@inheritDoc} */
- @Override
- public predicate
to a slice of the deque, toIndex
, exclusive, down
- * to fromIndex
, inclusive or until the predicate returns false
.
- */
- private void descendingForEach(BytePredicate predicate, int fromIndex, final int toIndex) {
- if (fromIndex == toIndex) return;
-
- final byte[] buffer = this.buffer;
- int i = toIndex;
- do {
- i = oneLeft(i, buffer.length);
- if (!predicate.apply(buffer[i])) {
- break;
- }
- } while (i != fromIndex);
- }
-
- /** {@inheritDoc} */
- @Override
- public int removeAll(BytePredicate predicate) {
- final byte[] buffer = this.buffer;
- final int last = tail;
- final int bufLen = buffer.length;
- int removed = 0;
- int from, to;
- from = to = head;
- try {
- for (from = to = head; from != last; from = oneRight(from, bufLen)) {
- if (predicate.apply(buffer[from])) {
- buffer[from] = ((byte) 0);
- removed++;
- continue;
- }
-
- if (to != from) {
- buffer[to] = buffer[from];
- buffer[from] = ((byte) 0);
- }
-
- to = oneRight(to, bufLen);
- }
- } finally {
- // Keep the deque in consistent state even if the predicate throws an exception.
- for (; from != last; from = oneRight(from, bufLen)) {
- if (to != from) {
- buffer[to] = buffer[from];
- buffer[from] = ((byte) 0);
- }
-
- to = oneRight(to, bufLen);
- }
- tail = to;
- }
-
- return removed;
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean contains(byte e) {
- int fromIndex = head;
- int toIndex = tail;
-
- final byte[] buffer = this.buffer;
- for (int i = fromIndex; i != toIndex; i = oneRight(i, buffer.length)) {
- if (((e) == (buffer[i]))) {
- return true;
- }
- }
-
- return false;
- }
-
- /** {@inheritDoc} */
- @Override
- public int hashCode() {
- int h = 1;
- int fromIndex = head;
- int toIndex = tail;
-
- final byte[] buffer = this.buffer;
- for (int i = fromIndex; i != toIndex; i = oneRight(i, buffer.length)) {
- h = 31 * h + BitMixer.mix(this.buffer[i]);
- }
- return h;
- }
-
- /**
- * Returns true
only if the other object is an instance of the same class and with
- * the same elements.
- */
- @Override
- public boolean equals(Object obj) {
- return (this == obj)
- || (obj != null && getClass() == obj.getClass() && equalElements(getClass().cast(obj)));
- }
-
- /** Compare order-aligned elements against another {@link ByteDeque}. */
- protected boolean equalElements(ByteArrayDeque other) {
- int max = size();
- if (other.size() != max) {
- return false;
- }
-
- Iteratoradd
- *
(vararg-version) or access the buffer directly (tight loop).
- */
- public void add(byte e1, byte e2) {
- ensureBufferSpace(2);
- buffer[elementsCount++] = e1;
- buffer[elementsCount++] = e2;
- }
-
- /** Add all elements from a range of given array to the list. */
- public void add(byte[] elements, int start, int length) {
- assert length >= 0 : "Length must be >= 0";
-
- ensureBufferSpace(length);
- System.arraycopy(elements, start, buffer, elementsCount, length);
- elementsCount += length;
- }
-
- /**
- * Vararg-signature method for adding elements at the end of the list.
- *
- * expectedAdditions
.
- * Increases internal buffer size if needed.
- */
- protected void ensureBufferSpace(int expectedAdditions) {
- final int bufferLen = (buffer == null ? 0 : buffer.length);
- if (elementsCount + expectedAdditions > bufferLen) {
- final int newSize = resizer.grow(bufferLen, elementsCount, expectedAdditions);
- assert newSize >= elementsCount + expectedAdditions
- : "Resizer failed to"
- + " return sensible new size: "
- + newSize
- + " <= "
- + (elementsCount + expectedAdditions);
-
- this.buffer = Arrays.copyOf(buffer, newSize);
- }
- }
-
- /**
- * Truncate or expand the list to the new size. If the list is truncated, the buffer will not be
- * reallocated (use {@link #trimToSize()} if you need a truncated buffer), but the truncated
- * values will be reset to the default value (zero). If the list is expanded, the elements beyond
- * the current size are initialized with JVM-defaults (zero or null
values).
- */
- public void resize(int newSize) {
- if (newSize <= buffer.length) {
- if (newSize < elementsCount) {
- Arrays.fill(buffer, newSize, elementsCount, ((byte) 0));
- } else {
- Arrays.fill(buffer, elementsCount, newSize, ((byte) 0));
- }
- } else {
- ensureCapacity(newSize);
- }
- this.elementsCount = newSize;
- }
-
- /** {@inheritDoc} */
- @Override
- public int size() {
- return elementsCount;
- }
-
- /** Trim the internal buffer to the current size. */
- public void trimToSize() {
- if (size() != this.buffer.length) {
- this.buffer = toArray();
- }
- }
-
- /**
- * Sets the number of stored elements to zero. Releases and initializes the internal storage array
- * to default values. To clear the list without cleaning the buffer, simply set the {@link
- * #elementsCount} field to zero.
- */
- @Override
- public void clear() {
- Arrays.fill(buffer, 0, elementsCount, ((byte) 0));
- this.elementsCount = 0;
- }
-
- /** Sets the number of stored elements to zero and releases the internal storage array. */
- @Override
- public void release() {
- this.buffer = EMPTY_ARRAY;
- this.elementsCount = 0;
- }
-
- /**
- * {@inheritDoc}
- *
- * true
only if the other object is an instance of the same class and with
- * the same elements.
- */
- @Override
- public boolean equals(Object obj) {
- return (this == obj)
- || (obj != null && getClass() == obj.getClass() && equalElements(getClass().cast(obj)));
- }
-
- /** Compare index-aligned elements against another {@link ByteIndexedContainer}. */
- protected boolean equalElements(ByteArrayList other) {
- int max = size();
- if (other.size() != max) {
- return false;
- }
-
- for (int i = 0; i < max; i++) {
- if (!((get(i)) == (other.get(i)))) {
- return false;
- }
- }
-
- return true;
- }
-
- @Override
- public long ramBytesAllocated() {
- // int: elementsCount
- return RamUsageEstimator.NUM_BYTES_OBJECT_HEADER
- + Integer.BYTES
- + resizer.ramBytesAllocated()
- + RamUsageEstimator.shallowSizeOfArray(buffer);
- }
-
- @Override
- public long ramBytesUsed() {
- // int: elementsCount
- return RamUsageEstimator.NUM_BYTES_OBJECT_HEADER
- + Integer.BYTES
- + resizer.ramBytesUsed()
- + RamUsageEstimator.shallowUsedSizeOfArray(buffer, elementsCount);
- }
-
- /** An iterator implementation for {@link ByteArrayList#iterator}. */
- static final class ValueIterator extends AbstractIteratorprocedure
to a slice of the list, fromIndex
, inclusive, to
- * toIndex
, exclusive.
- */
- public predicate
to a slice of the list, fromIndex
, inclusive, to
- * toIndex
, exclusive, or until predicate returns false
.
- */
- public byte
. The
- * elements are copied from the argument to the internal buffer.
- */
- public static ByteArrayList from(byte... elements) {
- final ByteArrayList list = new ByteArrayList(elements.length);
- list.add(elements);
- return list;
- }
-}
diff --git a/sources/main/java/com/carrotsearch/hppc/ByteBufferVisualizer.java b/sources/main/java/com/carrotsearch/hppc/ByteBufferVisualizer.java
deleted file mode 100644
index 0a39142a..00000000
--- a/sources/main/java/com/carrotsearch/hppc/ByteBufferVisualizer.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package com.carrotsearch.hppc;
-
-/**
- * Reused buffer visualization routines.
- *
- * @see ByteSet#visualizeKeyDistribution(int)
- * @see ByteVTypeMap#visualizeKeyDistribution(int)
- */
-class ByteBufferVisualizer {
- static String visualizeKeyDistribution(byte[] buffer, int max, int characters) {
- final StringBuilder b = new StringBuilder();
- final char[] chars = ".123456789X".toCharArray();
- for (int i = 1, start = -1; i <= characters; i++) {
- int end = (int) ((long) i * max / characters);
-
- if (start + 1 <= end) {
- int taken = 0;
- int slots = 0;
- for (int slot = start + 1; slot <= end; slot++, slots++) {
- if (!((buffer[slot]) == 0)) {
- taken++;
- }
- }
- b.append(chars[Math.min(chars.length - 1, taken * chars.length / slots)]);
- start = end;
- }
- }
- while (b.length() < characters) {
- b.append(' ');
- }
- return b.toString();
- }
-}
diff --git a/sources/main/java/com/carrotsearch/hppc/ByteCollection.java b/sources/main/java/com/carrotsearch/hppc/ByteCollection.java
deleted file mode 100644
index 2e89418e..00000000
--- a/sources/main/java/com/carrotsearch/hppc/ByteCollection.java
+++ /dev/null
@@ -1,64 +0,0 @@
-package com.carrotsearch.hppc;
-
-import com.carrotsearch.hppc.predicates.BytePredicate;
-
-/**
- * A collection allows basic, efficient operations on sets of elements (difference and
- * intersection).
- */
-@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeCollection.java")
-public interface ByteCollection extends ByteContainer {
- /**
- * Removes all occurrences of e
from this collection.
- *
- * @param e Element to be removed from this collection, if present.
- * @return The number of removed elements as a result of this call.
- */
- public int removeAll(byte e);
-
- /**
- * Removes all elements in this collection that are present in c
.
- *
- * @return Returns the number of removed elements.
- */
- public int removeAll(ByteLookupContainer c);
-
- /**
- * Removes all elements in this collection for which the given predicate returns true
- * .
- *
- * @return Returns the number of removed elements.
- */
- public int removeAll(BytePredicate predicate);
-
- /**
- * Keeps all elements in this collection that are present in c
. Runs in time
- * proportional to the number of elements in this collection. Equivalent of sets intersection.
- *
- * @return Returns the number of removed elements.
- */
- public int retainAll(ByteLookupContainer c);
-
- /**
- * Keeps all elements in this collection for which the given predicate returns true
.
- *
- * @return Returns the number of removed elements.
- */
- public int retainAll(BytePredicate predicate);
-
- /**
- * Removes all elements from this collection.
- *
- * @see #release()
- */
- public void clear();
-
- /**
- * Removes all elements from the collection and additionally releases any internal buffers.
- * Typically, if the object is to be reused, a simple {@link #clear()} should be a better
- * alternative since it'll avoid reallocation.
- *
- * @see #clear()
- */
- public void release();
-}
diff --git a/sources/main/java/com/carrotsearch/hppc/ByteContainer.java b/sources/main/java/com/carrotsearch/hppc/ByteContainer.java
deleted file mode 100644
index 19edc86b..00000000
--- a/sources/main/java/com/carrotsearch/hppc/ByteContainer.java
+++ /dev/null
@@ -1,76 +0,0 @@
-package com.carrotsearch.hppc;
-
-import com.carrotsearch.hppc.cursors.ByteCursor;
-import com.carrotsearch.hppc.predicates.BytePredicate;
-import com.carrotsearch.hppc.procedures.ByteProcedure;
-import java.util.Iterator;
-
-/** A generic container holding byte
s. */
-@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeContainer.java")
-public interface ByteContainer extends Iterable
- * for (ByteCursor<byte> c : container) {
- * System.out.println("index=" + c.index + " value=" + c.value);
- * }
- *
- */
- public Iteratortrue
if this container has an element equal to e
.
- */
- public boolean contains(byte e);
-
- /**
- * Return the current number of elements in this container. The time for calculating the
- * container's size may take O(n)
time, although implementing classes should try to
- * maintain the current size and return in constant time.
- */
- public int size();
-
- /** Shortcut for size() == 0
. */
- public boolean isEmpty();
-
- /**
- * Copies all elements of this container to an array.
- *
- * procedure
to all container elements. Returns the argument (any subclass
- * of {@link ByteProcedure}. This lets the caller to call methods of the argument by chaining the
- * call (even if the argument is an anonymous type) to retrieve computed values, for example
- * (IntContainer):
- *
- *
- * int count = container.forEach(new IntProcedure() {
- * int count; // this is a field declaration in an anonymous class.
- *
- * public void apply(int value) {
- * count++;
- * }
- * }).count;
- *
- */
- public predicate
to container elements as long, as the predicate returns
- * true
. The iteration is interrupted otherwise.
- */
- public e
.
- *
- * @return The deleted element's index or -1
if the element was not found.
- */
- public int removeFirst(byte e);
-
- /**
- * Removes the last element that equals e
.
- *
- * @return The deleted element's index or -1
if the element was not found.
- */
- public int removeLast(byte e);
-
- /** Inserts the specified element at the front of this deque. */
- public void addFirst(byte e);
-
- /** Inserts the specified element at the end of this deque. */
- public void addLast(byte e);
-
- /**
- * Retrieves and removes the first element of this deque.
- *
- * @return the head (first) element of this deque.
- */
- public byte removeFirst();
-
- /**
- * Retrieves and removes the last element of this deque.
- *
- * @return the tail of this deque.
- */
- public byte removeLast();
-
- /**
- * Retrieves the first element of this deque but does not remove it.
- *
- * @return the head of this deque.
- */
- public byte getFirst();
-
- /**
- * Retrieves the last element of this deque but does not remove it.
- *
- * @return the head of this deque.
- */
- public byte getLast();
-
- /**
- * @return An iterator over elements in this deque in tail-to-head order.
- */
- public Iteratorprocedure
to all elements in tail-to-head order. */
- public predicate
to container elements as long, as the predicate returns
- * true
. The iteration is interrupted otherwise.
- */
- public index
. Indexes
- * are zero-based.
- */
-@com.carrotsearch.hppc.Generated(
- date = "2024-06-04T15:20:17+0200",
- value = "KTypeIndexedContainer.java")
-public interface ByteIndexedContainer extends ByteCollection, RandomAccess {
- /**
- * Removes the first element that equals e1
, returning whether an element has been
- * removed.
- */
- public boolean removeElement(byte e1);
-
- /**
- * Removes the first element that equals e1
, returning its deleted position or
- * -1
if the element was not found.
- */
- public int removeFirst(byte e1);
-
- /**
- * Removes the last element that equals e1
, returning its deleted position or
- * -1
if the element was not found.
- */
- public int removeLast(byte e1);
-
- /**
- * Returns the index of the first occurrence of the specified element in this list, or -1 if this
- * list does not contain the element.
- */
- public int indexOf(byte e1);
-
- /**
- * Returns the index of the last occurrence of the specified element in this list, or -1 if this
- * list does not contain the element.
- */
- public int lastIndexOf(byte e1);
-
- /** Adds an element to the end of this container (the last index is incremented by one). */
- public void add(byte e1);
-
- /**
- * Inserts the specified element at the specified position in this list.
- *
- * @param index The index at which the element should be inserted, shifting any existing and
- * subsequent elements to the right.
- */
- public void insert(int index, byte e1);
-
- /**
- * Replaces the element at the specified position in this list with the specified element.
- *
- * @return Returns the previous value in the list.
- */
- public byte set(int index, byte e1);
-
- /**
- * @return Returns the element at index index
from the list.
- */
- public byte get(int index);
-
- /**
- * Removes the element at the specified position in this container and returns it.
- *
- * @see #removeFirst
- * @see #removeLast
- * @see #removeAll
- */
- public byte removeAt(int index);
-
- /** Removes and returns the last element of this container. This container must not be empty. */
- public byte removeLast();
-
- /**
- * Removes from this container all of the elements with indexes between fromIndex
,
- * inclusive, and toIndex
, exclusive.
- */
- public void removeRange(int fromIndex, int toIndex);
-
- /** Returns this container elements as a stream. */
-
- /** Sorts the elements in this container and returns this container. */
- public ByteIndexedContainer sort();
-
- /** Reverses the elements in this container and returns this container. */
- public ByteIndexedContainer reverse();
-}
diff --git a/sources/main/java/com/carrotsearch/hppc/ByteLookupContainer.java b/sources/main/java/com/carrotsearch/hppc/ByteLookupContainer.java
deleted file mode 100644
index ac41bc0b..00000000
--- a/sources/main/java/com/carrotsearch/hppc/ByteLookupContainer.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package com.carrotsearch.hppc;
-
-/**
- * Marker interface for containers that can check if they contain a given object in at least time
- * O(log n)
and ideally in amortized constant time O(1)
.
- */
-@com.carrotsearch.hppc.Generated(
- date = "2024-06-04T15:20:17+0200",
- value = "KTypeLookupContainer.java")
-public interface ByteLookupContainer extends ByteContainer {
- public boolean contains(byte e);
-}
diff --git a/sources/main/java/com/carrotsearch/hppc/ByteStack.java b/sources/main/java/com/carrotsearch/hppc/ByteStack.java
deleted file mode 100644
index 0cf32432..00000000
--- a/sources/main/java/com/carrotsearch/hppc/ByteStack.java
+++ /dev/null
@@ -1,137 +0,0 @@
-package com.carrotsearch.hppc;
-
-import com.carrotsearch.hppc.cursors.ByteCursor;
-
-/**
- * A subclass of {@link ByteArrayList} adding stack-related utility methods. The top of the stack is
- * at the {@link #size()} - 1
element.
- */
-@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeStack.java")
-public class ByteStack extends ByteArrayList {
- /** New instance with sane defaults. */
- public ByteStack() {
- super();
- }
-
- /**
- * New instance with sane defaults.
- *
- * @param expectedElements The expected number of elements guaranteed not to cause buffer
- * expansion (inclusive).
- */
- public ByteStack(int expectedElements) {
- super(expectedElements);
- }
-
- /**
- * New instance with sane defaults.
- *
- * @param expectedElements The expected number of elements guaranteed not to cause buffer
- * expansion (inclusive).
- * @param resizer Underlying buffer sizing strategy.
- */
- public ByteStack(int expectedElements, ArraySizingStrategy resizer) {
- super(expectedElements, resizer);
- }
-
- /** Create a stack by pushing all elements of another container to it. */
- public ByteStack(ByteContainer container) {
- super(container);
- }
-
- /** Adds one byte to the stack. */
- public void push(byte e1) {
- ensureBufferSpace(1);
- buffer[elementsCount++] = e1;
- }
-
- /** Adds two bytes to the stack. */
- public void push(byte e1, byte e2) {
- ensureBufferSpace(2);
- buffer[elementsCount++] = e1;
- buffer[elementsCount++] = e2;
- }
-
- /** Adds three bytes to the stack. */
- public void push(byte e1, byte e2, byte e3) {
- ensureBufferSpace(3);
- buffer[elementsCount++] = e1;
- buffer[elementsCount++] = e2;
- buffer[elementsCount++] = e3;
- }
-
- /** Adds four bytes to the stack. */
- public void push(byte e1, byte e2, byte e3, byte e4) {
- ensureBufferSpace(4);
- buffer[elementsCount++] = e1;
- buffer[elementsCount++] = e2;
- buffer[elementsCount++] = e3;
- buffer[elementsCount++] = e4;
- }
-
- /** Add a range of array elements to the stack. */
- public void push(byte[] elements, int start, int len) {
- assert start >= 0 && len >= 0;
-
- ensureBufferSpace(len);
- System.arraycopy(elements, start, buffer, elementsCount, len);
- elementsCount += len;
- }
-
- /**
- * Vararg-signature method for pushing elements at the top of the stack.
- *
- * e1
. The index
- * points to the {@link #buffer} array.
- *
- * @param e1 The element to look for.
- * @return Returns the index of the first element equal to e1
or -1
if
- * not found.
- */
- public int bufferIndexOf(char e1) {
- final int last = tail;
- final int bufLen = buffer.length;
- for (int i = head; i != last; i = oneRight(i, bufLen)) {
- if (((e1) == (buffer[i]))) {
- return i;
- }
- }
-
- return -1;
- }
-
- /** {@inheritDoc} */
- @Override
- public int removeLast(char e1) {
- final int index = lastBufferIndexOf(e1);
- if (index >= 0) {
- removeAtBufferIndex(index);
- }
- return index;
- }
-
- /**
- * Return the index of the last (counting from tail) element equal to e1
. The index
- * points to the {@link #buffer} array.
- *
- * @param e1 The element to look for.
- * @return Returns the index of the first element equal to e1
or -1
if
- * not found.
- */
- public int lastBufferIndexOf(char e1) {
- final int bufLen = buffer.length;
- final int last = oneLeft(head, bufLen);
- for (int i = oneLeft(tail, bufLen); i != last; i = oneLeft(i, bufLen)) {
- if (((e1) == (buffer[i]))) return i;
- }
-
- return -1;
- }
-
- /** {@inheritDoc} */
- @Override
- public int removeAll(char e1) {
- int removed = 0;
- final int last = tail;
- final int bufLen = buffer.length;
- int from, to;
- for (from = to = head; from != last; from = oneRight(from, bufLen)) {
- if (((e1) == (buffer[from]))) {
- buffer[from] = ((char) 0);
- removed++;
- continue;
- }
-
- if (to != from) {
- buffer[to] = buffer[from];
- buffer[from] = ((char) 0);
- }
-
- to = oneRight(to, bufLen);
- }
-
- tail = to;
- return removed;
- }
-
- /**
- * Removes the element at index
in the internal {#link {@link #buffer} array,
- * returning its value.
- *
- * @param index Index of the element to remove. The index must be located between {@link #head}
- * and {@link #tail} in modulo {@link #buffer} arithmetic.
- */
- public void removeAtBufferIndex(int index) {
- assert (head <= tail ? index >= head && index < tail : index >= head || index < tail)
- : "Index out of range (head=" + head + ", tail=" + tail + ", index=" + index + ").";
-
- // Cache fields in locals (hopefully moved to registers).
- final char[] buffer = this.buffer;
- final int bufLen = buffer.length;
- final int lastIndex = bufLen - 1;
- final int head = this.head;
- final int tail = this.tail;
-
- final int leftChunk = Math.abs(index - head) % bufLen;
- final int rightChunk = Math.abs(tail - index) % bufLen;
-
- if (leftChunk < rightChunk) {
- if (index >= head) {
- System.arraycopy(buffer, head, buffer, head + 1, leftChunk);
- } else {
- System.arraycopy(buffer, 0, buffer, 1, index);
- buffer[0] = buffer[lastIndex];
- System.arraycopy(buffer, head, buffer, head + 1, lastIndex - head);
- }
- buffer[head] = ((char) 0);
- this.head = oneRight(head, bufLen);
- } else {
- if (index < tail) {
- System.arraycopy(buffer, index + 1, buffer, index, rightChunk);
- } else {
- System.arraycopy(buffer, index + 1, buffer, index, lastIndex - index);
- buffer[lastIndex] = buffer[0];
- System.arraycopy(buffer, 1, buffer, 0, tail);
- }
- buffer[tail] = ((char) 0);
- this.tail = oneLeft(tail, bufLen);
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean isEmpty() {
- return size() == 0;
- }
-
- /** {@inheritDoc} */
- @Override
- public int size() {
- if (head <= tail) return tail - head;
- else return (tail - head + buffer.length);
- }
-
- /**
- * {@inheritDoc}
- *
- * expectedAdditions
.
- * Increases internal buffer size if needed.
- */
- protected void ensureBufferSpace(int expectedAdditions) {
- final int bufferLen = buffer.length;
- final int elementsCount = size();
-
- if (elementsCount + expectedAdditions >= bufferLen) {
- final int emptySlot = 1; // deque invariant: always an empty slot.
- final int newSize = resizer.grow(bufferLen, elementsCount + emptySlot, expectedAdditions);
- assert newSize >= (elementsCount + expectedAdditions + emptySlot)
- : "Resizer failed to"
- + " return sensible new size: "
- + newSize
- + " <= "
- + (elementsCount + expectedAdditions);
-
- try {
- final char[] newBuffer = (new char[newSize]);
- if (bufferLen > 0) {
- toArray(newBuffer);
- tail = elementsCount;
- head = 0;
- }
- this.buffer = newBuffer;
- } catch (OutOfMemoryError e) {
- throw new BufferAllocationException(
- "Not enough memory to allocate new buffers: %,d -> %,d", e, bufferLen, newSize);
- }
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public char[] toArray() {
-
- final int size = size();
- return toArray((new char[size]));
- }
-
- /**
- * Copies elements of this deque to an array. The content of the target
array is
- * filled from index 0 (head of the queue) to index size() - 1
(tail of the queue).
- *
- * @param target The target array must be large enough to hold all elements.
- * @return Returns the target argument for chaining.
- */
- public char[] toArray(char[] target) {
- assert target.length >= size() : "Target array must be >= " + size();
-
- if (head < tail) {
- // The contents is not wrapped around. Just copy.
- System.arraycopy(buffer, head, target, 0, size());
- } else if (head > tail) {
- // The contents is split. Merge elements from the following indexes:
- // [head...buffer.length - 1][0, tail - 1]
- final int rightCount = buffer.length - head;
- System.arraycopy(buffer, head, target, 0, rightCount);
- System.arraycopy(buffer, 0, target, rightCount, tail);
- }
-
- return target;
- }
-
- /**
- * Clone this object. The returned clone will reuse the same hash function and array resizing
- * strategy.
- */
- @Override
- public CharArrayDeque clone() {
- try {
-
- CharArrayDeque cloned = (CharArrayDeque) super.clone();
- cloned.buffer = buffer.clone();
- return cloned;
- } catch (CloneNotSupportedException e) {
- throw new RuntimeException(e);
- }
- }
-
- /** Move one index to the left, wrapping around buffer. */
- protected static int oneLeft(int index, int modulus) {
- if (index >= 1) {
- return index - 1;
- }
- return modulus - 1;
- }
-
- /** Move one index to the right, wrapping around buffer. */
- protected static int oneRight(int index, int modulus) {
- if (index + 1 == modulus) {
- return 0;
- }
- return index + 1;
- }
-
- @Override
- public long ramBytesAllocated() {
- // int: head, tail
- return RamUsageEstimator.NUM_BYTES_OBJECT_HEADER
- + Integer.BYTES * 2
- + resizer.ramBytesAllocated()
- + RamUsageEstimator.shallowSizeOfArray(buffer);
- }
-
- @Override
- public long ramBytesUsed() {
- // int: head, tail
- return RamUsageEstimator.NUM_BYTES_OBJECT_HEADER
- + Integer.BYTES * 2
- + resizer.ramBytesUsed()
- + RamUsageEstimator.shallowUsedSizeOfArray(buffer, size());
- }
-
- /** An iterator implementation for {@link ObjectArrayDeque#iterator}. */
- private final class ValueIterator extends AbstractIterator
- * for (IntValueCursor c : intDeque) {
- * System.out.println("buffer index=" + c.index + " value=" + c.value);
- * }
- *
- */
- public Iterator
- * for (Iterator<IntCursor> i = intDeque.descendingIterator(); i.hasNext();) {
- * final IntCursor c = i.next();
- * System.out.println("buffer index=" + c.index + " value=" + c.value);
- * }
- *
- */
- public Iteratorprocedure
to a slice of the deque, fromIndex
, inclusive, to
- * toIndex
, exclusive.
- */
- private void forEach(CharProcedure procedure, int fromIndex, final int toIndex) {
- final char[] buffer = this.buffer;
- for (int i = fromIndex; i != toIndex; i = oneRight(i, buffer.length)) {
- procedure.apply(buffer[i]);
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public procedure
to all elements of this deque, tail to head. */
- @Override
- public procedure
to a slice of the deque, toIndex
, exclusive, down
- * to fromIndex
, inclusive.
- */
- private void descendingForEach(CharProcedure procedure, int fromIndex, final int toIndex) {
- if (fromIndex == toIndex) return;
-
- final char[] buffer = this.buffer;
- int i = toIndex;
- do {
- i = oneLeft(i, buffer.length);
- procedure.apply(buffer[i]);
- } while (i != fromIndex);
- }
-
- /** {@inheritDoc} */
- @Override
- public predicate
to a slice of the deque, toIndex
, exclusive, down
- * to fromIndex
, inclusive or until the predicate returns false
.
- */
- private void descendingForEach(CharPredicate predicate, int fromIndex, final int toIndex) {
- if (fromIndex == toIndex) return;
-
- final char[] buffer = this.buffer;
- int i = toIndex;
- do {
- i = oneLeft(i, buffer.length);
- if (!predicate.apply(buffer[i])) {
- break;
- }
- } while (i != fromIndex);
- }
-
- /** {@inheritDoc} */
- @Override
- public int removeAll(CharPredicate predicate) {
- final char[] buffer = this.buffer;
- final int last = tail;
- final int bufLen = buffer.length;
- int removed = 0;
- int from, to;
- from = to = head;
- try {
- for (from = to = head; from != last; from = oneRight(from, bufLen)) {
- if (predicate.apply(buffer[from])) {
- buffer[from] = ((char) 0);
- removed++;
- continue;
- }
-
- if (to != from) {
- buffer[to] = buffer[from];
- buffer[from] = ((char) 0);
- }
-
- to = oneRight(to, bufLen);
- }
- } finally {
- // Keep the deque in consistent state even if the predicate throws an exception.
- for (; from != last; from = oneRight(from, bufLen)) {
- if (to != from) {
- buffer[to] = buffer[from];
- buffer[from] = ((char) 0);
- }
-
- to = oneRight(to, bufLen);
- }
- tail = to;
- }
-
- return removed;
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean contains(char e) {
- int fromIndex = head;
- int toIndex = tail;
-
- final char[] buffer = this.buffer;
- for (int i = fromIndex; i != toIndex; i = oneRight(i, buffer.length)) {
- if (((e) == (buffer[i]))) {
- return true;
- }
- }
-
- return false;
- }
-
- /** {@inheritDoc} */
- @Override
- public int hashCode() {
- int h = 1;
- int fromIndex = head;
- int toIndex = tail;
-
- final char[] buffer = this.buffer;
- for (int i = fromIndex; i != toIndex; i = oneRight(i, buffer.length)) {
- h = 31 * h + BitMixer.mix(this.buffer[i]);
- }
- return h;
- }
-
- /**
- * Returns true
only if the other object is an instance of the same class and with
- * the same elements.
- */
- @Override
- public boolean equals(Object obj) {
- return (this == obj)
- || (obj != null && getClass() == obj.getClass() && equalElements(getClass().cast(obj)));
- }
-
- /** Compare order-aligned elements against another {@link CharDeque}. */
- protected boolean equalElements(CharArrayDeque other) {
- int max = size();
- if (other.size() != max) {
- return false;
- }
-
- Iteratoradd
- *
(vararg-version) or access the buffer directly (tight loop).
- */
- public void add(char e1, char e2) {
- ensureBufferSpace(2);
- buffer[elementsCount++] = e1;
- buffer[elementsCount++] = e2;
- }
-
- /** Add all elements from a range of given array to the list. */
- public void add(char[] elements, int start, int length) {
- assert length >= 0 : "Length must be >= 0";
-
- ensureBufferSpace(length);
- System.arraycopy(elements, start, buffer, elementsCount, length);
- elementsCount += length;
- }
-
- /**
- * Vararg-signature method for adding elements at the end of the list.
- *
- * expectedAdditions
.
- * Increases internal buffer size if needed.
- */
- protected void ensureBufferSpace(int expectedAdditions) {
- final int bufferLen = (buffer == null ? 0 : buffer.length);
- if (elementsCount + expectedAdditions > bufferLen) {
- final int newSize = resizer.grow(bufferLen, elementsCount, expectedAdditions);
- assert newSize >= elementsCount + expectedAdditions
- : "Resizer failed to"
- + " return sensible new size: "
- + newSize
- + " <= "
- + (elementsCount + expectedAdditions);
-
- this.buffer = Arrays.copyOf(buffer, newSize);
- }
- }
-
- /**
- * Truncate or expand the list to the new size. If the list is truncated, the buffer will not be
- * reallocated (use {@link #trimToSize()} if you need a truncated buffer), but the truncated
- * values will be reset to the default value (zero). If the list is expanded, the elements beyond
- * the current size are initialized with JVM-defaults (zero or null
values).
- */
- public void resize(int newSize) {
- if (newSize <= buffer.length) {
- if (newSize < elementsCount) {
- Arrays.fill(buffer, newSize, elementsCount, ((char) 0));
- } else {
- Arrays.fill(buffer, elementsCount, newSize, ((char) 0));
- }
- } else {
- ensureCapacity(newSize);
- }
- this.elementsCount = newSize;
- }
-
- /** {@inheritDoc} */
- @Override
- public int size() {
- return elementsCount;
- }
-
- /** Trim the internal buffer to the current size. */
- public void trimToSize() {
- if (size() != this.buffer.length) {
- this.buffer = toArray();
- }
- }
-
- /**
- * Sets the number of stored elements to zero. Releases and initializes the internal storage array
- * to default values. To clear the list without cleaning the buffer, simply set the {@link
- * #elementsCount} field to zero.
- */
- @Override
- public void clear() {
- Arrays.fill(buffer, 0, elementsCount, ((char) 0));
- this.elementsCount = 0;
- }
-
- /** Sets the number of stored elements to zero and releases the internal storage array. */
- @Override
- public void release() {
- this.buffer = EMPTY_ARRAY;
- this.elementsCount = 0;
- }
-
- /**
- * {@inheritDoc}
- *
- * true
only if the other object is an instance of the same class and with
- * the same elements.
- */
- @Override
- public boolean equals(Object obj) {
- return (this == obj)
- || (obj != null && getClass() == obj.getClass() && equalElements(getClass().cast(obj)));
- }
-
- /** Compare index-aligned elements against another {@link CharIndexedContainer}. */
- protected boolean equalElements(CharArrayList other) {
- int max = size();
- if (other.size() != max) {
- return false;
- }
-
- for (int i = 0; i < max; i++) {
- if (!((get(i)) == (other.get(i)))) {
- return false;
- }
- }
-
- return true;
- }
-
- @Override
- public long ramBytesAllocated() {
- // int: elementsCount
- return RamUsageEstimator.NUM_BYTES_OBJECT_HEADER
- + Integer.BYTES
- + resizer.ramBytesAllocated()
- + RamUsageEstimator.shallowSizeOfArray(buffer);
- }
-
- @Override
- public long ramBytesUsed() {
- // int: elementsCount
- return RamUsageEstimator.NUM_BYTES_OBJECT_HEADER
- + Integer.BYTES
- + resizer.ramBytesUsed()
- + RamUsageEstimator.shallowUsedSizeOfArray(buffer, elementsCount);
- }
-
- /** An iterator implementation for {@link CharArrayList#iterator}. */
- static final class ValueIterator extends AbstractIteratorprocedure
to a slice of the list, fromIndex
, inclusive, to
- * toIndex
, exclusive.
- */
- public predicate
to a slice of the list, fromIndex
, inclusive, to
- * toIndex
, exclusive, or until predicate returns false
.
- */
- public char
. The
- * elements are copied from the argument to the internal buffer.
- */
- public static CharArrayList from(char... elements) {
- final CharArrayList list = new CharArrayList(elements.length);
- list.add(elements);
- return list;
- }
-}
diff --git a/sources/main/java/com/carrotsearch/hppc/CharBufferVisualizer.java b/sources/main/java/com/carrotsearch/hppc/CharBufferVisualizer.java
deleted file mode 100644
index 7bd17436..00000000
--- a/sources/main/java/com/carrotsearch/hppc/CharBufferVisualizer.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package com.carrotsearch.hppc;
-
-/**
- * Reused buffer visualization routines.
- *
- * @see CharSet#visualizeKeyDistribution(int)
- * @see CharVTypeMap#visualizeKeyDistribution(int)
- */
-class CharBufferVisualizer {
- static String visualizeKeyDistribution(char[] buffer, int max, int characters) {
- final StringBuilder b = new StringBuilder();
- final char[] chars = ".123456789X".toCharArray();
- for (int i = 1, start = -1; i <= characters; i++) {
- int end = (int) ((long) i * max / characters);
-
- if (start + 1 <= end) {
- int taken = 0;
- int slots = 0;
- for (int slot = start + 1; slot <= end; slot++, slots++) {
- if (!((buffer[slot]) == 0)) {
- taken++;
- }
- }
- b.append(chars[Math.min(chars.length - 1, taken * chars.length / slots)]);
- start = end;
- }
- }
- while (b.length() < characters) {
- b.append(' ');
- }
- return b.toString();
- }
-}
diff --git a/sources/main/java/com/carrotsearch/hppc/CharByteAssociativeContainer.java b/sources/main/java/com/carrotsearch/hppc/CharByteAssociativeContainer.java
deleted file mode 100644
index a69b4beb..00000000
--- a/sources/main/java/com/carrotsearch/hppc/CharByteAssociativeContainer.java
+++ /dev/null
@@ -1,105 +0,0 @@
-package com.carrotsearch.hppc;
-
-import com.carrotsearch.hppc.cursors.*;
-import com.carrotsearch.hppc.predicates.*;
-import com.carrotsearch.hppc.procedures.*;
-import java.util.Iterator;
-
-/**
- * An associative container from keys to (one or possibly more) values.
- *
- * @see CharContainer
- */
-@com.carrotsearch.hppc.Generated(
- date = "2024-06-04T15:20:17+0200",
- value = "KTypeVTypeAssociativeContainer.java")
-public interface CharByteAssociativeContainer extends Iterable
- * for (IntShortCursor c : intShortMap) {
- * System.out.println("index=" + c.index + " key=" + c.key + " value=" + c.value);
- * }
- *
- * index
field inside the cursor gives the internal index inside the
- * container's implementation. The interpretation of this index depends on to the container.
- */
- @Override
- public Iteratortrue
if this container has an association to a value for the given key.
- */
- public boolean containsKey(char key);
-
- /**
- * @return Returns the current size (number of assigned keys) in the container.
- */
- public int size();
-
- /**
- * @return Return true
if this hash map contains no assigned keys.
- */
- public boolean isEmpty();
-
- /**
- * Removes all keys (and associated values) present in a given container. An alias to:
- *
- *
- * keys().removeAll(container)
- *
- *
- * but with no additional overhead.
- *
- * @return Returns the number of elements actually removed as a result of this call.
- */
- public int removeAll(CharContainer container);
-
- /**
- * Removes all keys (and associated values) for which the predicate returns true
.
- *
- * @return Returns the number of elements actually removed as a result of this call.
- */
- public int removeAll(CharPredicate predicate);
-
- /**
- * Removes all keys (and associated values) for which the predicate returns true
.
- *
- * @return Returns the number of elements actually removed as a result of this call.
- */
- public int removeAll(CharBytePredicate predicate);
-
- /**
- * Applies a given procedure to all keys-value pairs in this container. Returns the argument (any
- * subclass of {@link CharByteProcedure}. This lets the caller call methods of the argument by
- * chaining the call (even if the argument is an anonymous type) to retrieve computed values.
- */
- public true
.
- */
- public char
to byte
, implemented using open addressing with
- * linear probing for collision resolution.
- *
- * @see HPPC interfaces diagram
- */
-@com.carrotsearch.hppc.Generated(
- date = "2024-06-04T15:20:16+0200",
- value = "KTypeVTypeHashMap.java")
-public class CharByteHashMap implements CharByteMap, Preallocable, Cloneable, Accountable {
-
- /** The array holding keys. */
- public char[] keys;
-
- /** The array holding values. */
- public byte[] values;
-
- /**
- * The number of stored keys (assigned key slots), excluding the special "empty" key, if any (use
- * {@link #size()} instead).
- *
- * @see #size()
- */
- protected int assigned;
-
- /** Mask for slot scans in {@link #keys}. */
- protected int mask;
-
- /** Expand (rehash) {@link #keys} when {@link #assigned} hits this value. */
- protected int resizeAt;
-
- /** Special treatment for the "empty slot" key marker. */
- protected boolean hasEmptyKey;
-
- /** The load factor for {@link #keys}. */
- protected double loadFactor;
-
- /** Seed used to ensure the hash iteration order is different from an iteration to another. */
- protected int iterationSeed;
-
- /** New instance with sane defaults. */
- public CharByteHashMap() {
- this(DEFAULT_EXPECTED_ELEMENTS);
- }
-
- /**
- * New instance with sane defaults.
- *
- * @param expectedElements The expected number of elements guaranteed not to cause buffer
- * expansion (inclusive).
- */
- public CharByteHashMap(int expectedElements) {
- this(expectedElements, DEFAULT_LOAD_FACTOR);
- }
-
- /**
- * New instance with the provided defaults.
- *
- * @param expectedElements The expected number of elements guaranteed not to cause a rehash
- * (inclusive).
- * @param loadFactor The load factor for internal buffers. Insane load factors (zero, full
- * capacity) are rejected by {@link #verifyLoadFactor(double)}.
- */
- public CharByteHashMap(int expectedElements, double loadFactor) {
- this.loadFactor = verifyLoadFactor(loadFactor);
- iterationSeed = HashContainers.nextIterationSeed();
- ensureCapacity(expectedElements);
- }
-
- /** Create a hash map from all key-value pairs of another container. */
- public CharByteHashMap(CharByteAssociativeContainer container) {
- this(container.size());
- putAll(container);
- }
-
- /** {@inheritDoc} */
- @Override
- public byte put(char key, byte value) {
- assert assigned < mask + 1;
-
- final int mask = this.mask;
- if (((key) == 0)) {
- byte previousValue = hasEmptyKey ? values[mask + 1] : ((byte) 0);
- hasEmptyKey = true;
- values[mask + 1] = value;
- return previousValue;
- } else {
- final char[] keys = this.keys;
- int slot = hashKey(key) & mask;
-
- char existing;
- while (!((existing = keys[slot]) == 0)) {
- if (((key) == (existing))) {
- final byte previousValue = values[slot];
- values[slot] = value;
- return previousValue;
- }
- slot = (slot + 1) & mask;
- }
-
- if (assigned == resizeAt) {
- allocateThenInsertThenRehash(slot, key, value);
- } else {
- keys[slot] = key;
- values[slot] = value;
- }
-
- assigned++;
- return ((byte) 0);
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public int putAll(CharByteAssociativeContainer container) {
- final int count = size();
- for (CharByteCursor c : container) {
- put(c.key, c.value);
- }
- return size() - count;
- }
-
- /** Puts all key/value pairs from a given iterable into this map. */
- @Override
- public int putAll(Iterable extends CharByteCursor> iterable) {
- final int count = size();
- for (CharByteCursor c : iterable) {
- put(c.key, c.value);
- }
- return size() - count;
- }
-
- /**
- * If key
exists, putValue
is inserted into the map, otherwise any
- * existing value is incremented by additionValue
.
- *
- * @param key The key of the value to adjust.
- * @param putValue The value to put if key
does not exist.
- * @param incrementValue The value to add to the existing value if key
exists.
- * @return Returns the current value associated with key
(after changes).
- */
- @Override
- public byte putOrAdd(char key, byte putValue, byte incrementValue) {
- assert assigned < mask + 1;
-
- int keyIndex = indexOf(key);
- if (indexExists(keyIndex)) {
- putValue = ((byte) ((values[keyIndex]) + (incrementValue)));
- indexReplace(keyIndex, putValue);
- } else {
- indexInsert(keyIndex, key, putValue);
- }
- return putValue;
- }
-
- /**
- * Adds incrementValue
to any existing value for the given key
or
- * inserts incrementValue
if key
did not previously exist.
- *
- * @param key The key of the value to adjust.
- * @param incrementValue The value to put or add to the existing value if key
exists.
- * @return Returns the current value associated with key
(after changes).
- */
- @Override
- public byte addTo(char key, byte incrementValue) {
- return putOrAdd(key, incrementValue, incrementValue);
- }
-
- /** {@inheritDoc} */
- @Override
- public byte remove(char key) {
- final int mask = this.mask;
- if (((key) == 0)) {
- if (!hasEmptyKey) {
- return ((byte) 0);
- }
- hasEmptyKey = false;
- byte previousValue = values[mask + 1];
- values[mask + 1] = ((byte) 0);
- return previousValue;
- } else {
- final char[] keys = this.keys;
- int slot = hashKey(key) & mask;
-
- char existing;
- while (!((existing = keys[slot]) == 0)) {
- if (((key) == (existing))) {
- final byte previousValue = values[slot];
- shiftConflictingKeys(slot);
- return previousValue;
- }
- slot = (slot + 1) & mask;
- }
-
- return ((byte) 0);
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public int removeAll(CharContainer other) {
- final int before = size();
-
- // Try to iterate over the smaller set of values or
- // over the container that isn't implementing
- // efficient contains() lookup.
-
- if (other.size() >= size() && other instanceof CharLookupContainer) {
- if (hasEmptyKey && other.contains(((char) 0))) {
- hasEmptyKey = false;
- values[mask + 1] = ((byte) 0);
- }
-
- final char[] keys = this.keys;
- for (int slot = 0, max = this.mask; slot <= max; ) {
- char existing;
- if (!((existing = keys[slot]) == 0) && other.contains(existing)) {
- // Shift, do not increment slot.
- shiftConflictingKeys(slot);
- } else {
- slot++;
- }
- }
- } else {
- for (CharCursor c : other) {
- remove(c.value);
- }
- }
-
- return before - size();
- }
-
- /** {@inheritDoc} */
- @Override
- public int removeAll(CharBytePredicate predicate) {
- final int before = size();
-
- final int mask = this.mask;
-
- if (hasEmptyKey) {
- if (predicate.apply(((char) 0), values[mask + 1])) {
- hasEmptyKey = false;
- values[mask + 1] = ((byte) 0);
- }
- }
-
- final char[] keys = this.keys;
- final byte[] values = this.values;
- for (int slot = 0; slot <= mask; ) {
- char existing;
- if (!((existing = keys[slot]) == 0) && predicate.apply(existing, values[slot])) {
- // Shift, do not increment slot.
- shiftConflictingKeys(slot);
- } else {
- slot++;
- }
- }
-
- return before - size();
- }
-
- /** {@inheritDoc} */
- @Override
- public int removeAll(CharPredicate predicate) {
- final int before = size();
-
- if (hasEmptyKey) {
- if (predicate.apply(((char) 0))) {
- hasEmptyKey = false;
- values[mask + 1] = ((byte) 0);
- }
- }
-
- final char[] keys = this.keys;
- for (int slot = 0, max = this.mask; slot <= max; ) {
- char existing;
- if (!((existing = keys[slot]) == 0) && predicate.apply(existing)) {
- // Shift, do not increment slot.
- shiftConflictingKeys(slot);
- } else {
- slot++;
- }
- }
-
- return before - size();
- }
-
- /** {@inheritDoc} */
- @Override
- public byte get(char key) {
- if (((key) == 0)) {
- return hasEmptyKey ? values[mask + 1] : ((byte) 0);
- } else {
- final char[] keys = this.keys;
- final int mask = this.mask;
- int slot = hashKey(key) & mask;
-
- char existing;
- while (!((existing = keys[slot]) == 0)) {
- if (((key) == (existing))) {
- return values[slot];
- }
- slot = (slot + 1) & mask;
- }
-
- return ((byte) 0);
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public byte getOrDefault(char key, byte defaultValue) {
- if (((key) == 0)) {
- return hasEmptyKey ? values[mask + 1] : defaultValue;
- } else {
- final char[] keys = this.keys;
- final int mask = this.mask;
- int slot = hashKey(key) & mask;
-
- char existing;
- while (!((existing = keys[slot]) == 0)) {
- if (((key) == (existing))) {
- return values[slot];
- }
- slot = (slot + 1) & mask;
- }
-
- return defaultValue;
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean containsKey(char key) {
- if (((key) == 0)) {
- return hasEmptyKey;
- } else {
- final char[] keys = this.keys;
- final int mask = this.mask;
- int slot = hashKey(key) & mask;
-
- char existing;
- while (!((existing = keys[slot]) == 0)) {
- if (((key) == (existing))) {
- return true;
- }
- slot = (slot + 1) & mask;
- }
-
- return false;
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public int indexOf(char key) {
- final int mask = this.mask;
- if (((key) == 0)) {
- return hasEmptyKey ? mask + 1 : ~(mask + 1);
- } else {
- final char[] keys = this.keys;
- int slot = hashKey(key) & mask;
-
- char existing;
- while (!((existing = keys[slot]) == 0)) {
- if (((key) == (existing))) {
- return slot;
- }
- slot = (slot + 1) & mask;
- }
-
- return ~slot;
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean indexExists(int index) {
- assert index < 0 || (index >= 0 && index <= mask) || (index == mask + 1 && hasEmptyKey);
-
- return index >= 0;
- }
-
- /** {@inheritDoc} */
- @Override
- public byte indexGet(int index) {
- assert index >= 0 : "The index must point at an existing key.";
- assert index <= mask || (index == mask + 1 && hasEmptyKey);
-
- return values[index];
- }
-
- /** {@inheritDoc} */
- @Override
- public byte indexReplace(int index, byte newValue) {
- assert index >= 0 : "The index must point at an existing key.";
- assert index <= mask || (index == mask + 1 && hasEmptyKey);
-
- byte previousValue = values[index];
- values[index] = newValue;
- return previousValue;
- }
-
- /** {@inheritDoc} */
- @Override
- public void indexInsert(int index, char key, byte value) {
- assert index < 0 : "The index must not point at an existing key.";
-
- index = ~index;
- if (((key) == 0)) {
- assert index == mask + 1;
- values[index] = value;
- hasEmptyKey = true;
- } else {
- assert ((keys[index]) == 0);
-
- if (assigned == resizeAt) {
- allocateThenInsertThenRehash(index, key, value);
- } else {
- keys[index] = key;
- values[index] = value;
- }
-
- assigned++;
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public byte indexRemove(int index) {
- assert index >= 0 : "The index must point at an existing key.";
- assert index <= mask || (index == mask + 1 && hasEmptyKey);
-
- byte previousValue = values[index];
- if (index > mask) {
- assert index == mask + 1;
- hasEmptyKey = false;
- values[index] = ((byte) 0);
- } else {
- shiftConflictingKeys(index);
- }
- return previousValue;
- }
-
- /** {@inheritDoc} */
- @Override
- public void clear() {
- assigned = 0;
- hasEmptyKey = false;
-
- Arrays.fill(keys, ((char) 0));
- }
-
- /** {@inheritDoc} */
- @Override
- public void release() {
- assigned = 0;
- hasEmptyKey = false;
-
- keys = null;
- values = null;
- ensureCapacity(Containers.DEFAULT_EXPECTED_ELEMENTS);
- }
-
- /** {@inheritDoc} */
- @Override
- public int size() {
- return assigned + (hasEmptyKey ? 1 : 0);
- }
-
- /** {@inheritDoc} */
- public boolean isEmpty() {
- return size() == 0;
- }
-
- /** {@inheritDoc} */
- @Override
- public int hashCode() {
- int h = hasEmptyKey ? 0xDEADBEEF : 0;
- for (CharByteCursor c : this) {
- h += BitMixer.mix(c.key) + BitMixer.mix(c.value);
- }
- return h;
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean equals(Object obj) {
- return (this == obj)
- || (obj != null && getClass() == obj.getClass() && equalElements(getClass().cast(obj)));
- }
-
- /** Return true if all keys of some other container exist in this container. */
- protected boolean equalElements(CharByteHashMap other) {
- if (other.size() != size()) {
- return false;
- }
-
- for (CharByteCursor c : other) {
- char key = c.key;
- if (!containsKey(key) || !((c.value) == (get(key)))) {
- return false;
- }
- }
-
- return true;
- }
-
- /**
- * Ensure this container can hold at least the given number of keys (entries) without resizing its
- * buffers.
- *
- * @param expectedElements The total number of keys, inclusive.
- */
- @Override
- public void ensureCapacity(int expectedElements) {
- if (expectedElements > resizeAt || keys == null) {
- final char[] prevKeys = this.keys;
- final byte[] prevValues = this.values;
- allocateBuffers(minBufferSize(expectedElements, loadFactor));
- if (prevKeys != null && !isEmpty()) {
- rehash(prevKeys, prevValues);
- }
- }
- }
-
- @Override
- public long ramBytesAllocated() {
- // int: iterationSeed, assigned, mask, resizeAt
- // double: loadFactor
- // boolean: hasEmptyKey
- return RamUsageEstimator.NUM_BYTES_OBJECT_HEADER
- + 4 * Integer.BYTES
- + Double.BYTES
- + 1
- + RamUsageEstimator.shallowSizeOfArray(keys)
- + RamUsageEstimator.shallowSizeOfArray(values);
- }
-
- @Override
- public long ramBytesUsed() {
- // int: iterationSeed, assigned, mask, resizeAt
- // double: loadFactor
- // boolean: hasEmptyKey
- return RamUsageEstimator.NUM_BYTES_OBJECT_HEADER
- + 4 * Integer.BYTES
- + Double.BYTES
- + 1
- + RamUsageEstimator.shallowUsedSizeOfArray(keys, size())
- + RamUsageEstimator.shallowUsedSizeOfArray(values, size());
- }
-
- /**
- * Provides the next iteration seed used to build the iteration starting slot and offset
- * increment. This method does not need to be synchronized, what matters is that each thread gets
- * a sequence of varying seeds.
- */
- protected int nextIterationSeed() {
- return iterationSeed = BitMixer.mixPhi(iterationSeed);
- }
-
- /** An iterator implementation for {@link #iterator}. */
- private final class EntryIterator extends AbstractIteratorslot
.
- */
- protected void shiftConflictingKeys(int gapSlot) {
- final char[] keys = this.keys;
- final byte[] values = this.values;
- final int mask = this.mask;
-
- // Perform shifts of conflicting keys to fill in the gap.
- int distance = 0;
- while (true) {
- final int slot = (gapSlot + (++distance)) & mask;
- final char existing = keys[slot];
- if (((existing) == 0)) {
- break;
- }
-
- final int idealSlot = hashKey(existing);
- final int shift = (slot - idealSlot) & mask;
- if (shift >= distance) {
- // Entry at this position was originally at or before the gap slot.
- // Move the conflict-shifted entry to the gap's position and repeat the procedure
- // for any entries to the right of the current position, treating it
- // as the new gap.
- keys[gapSlot] = existing;
- values[gapSlot] = values[slot];
- gapSlot = slot;
- distance = 0;
- }
- }
-
- // Mark the last found gap slot without a conflict as empty.
- keys[gapSlot] = ((char) 0);
- values[gapSlot] = ((byte) 0);
- assigned--;
- }
-}
diff --git a/sources/main/java/com/carrotsearch/hppc/CharByteMap.java b/sources/main/java/com/carrotsearch/hppc/CharByteMap.java
deleted file mode 100644
index dcb4ef54..00000000
--- a/sources/main/java/com/carrotsearch/hppc/CharByteMap.java
+++ /dev/null
@@ -1,205 +0,0 @@
-package com.carrotsearch.hppc;
-
-import com.carrotsearch.hppc.cursors.CharByteCursor;
-
-/** An associative container with unique binding from keys to a single value. */
-@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeVTypeMap.java")
-public interface CharByteMap extends CharByteAssociativeContainer {
- /**
- * @return Returns the value associated with the given key or the default value for the value
- * type, if the key is not associated with any value. For numeric value types, this default
- * value is 0, for object types it is {@code null}.
- */
- public byte get(char key);
-
- /**
- * @return Returns the value associated with the given key or the provided default value if the
- * key is not associated with any value.
- */
- public byte getOrDefault(char key, byte defaultValue);
-
- /**
- * Place a given key and value in the container.
- *
- * @return The value previously stored under the given key in the map is returned.
- */
- public byte put(char key, byte value);
-
- /**
- * If the specified key is not already associated with a value, associates it with the given
- * value.
- *
- * @return {@code true} if {@code key} did not exist and {@code value} was placed in the map,
- * {@code false} otherwise.
- */
- public default boolean putIfAbsent(char key, byte value) {
- int keyIndex = indexOf(key);
- if (indexExists(keyIndex)) {
- return false;
- } else {
- indexInsert(keyIndex, key, value);
- return true;
- }
- }
-
- /**
- * Puts all keys from another container to this map, replacing the values of existing keys, if
- * such keys are present.
- *
- * @return Returns the number of keys added to the map as a result of this call (not previously
- * present in the map). Values of existing keys are overwritten.
- */
- public int putAll(CharByteAssociativeContainer container);
-
- /**
- * Puts all keys from an iterable cursor to this map, replacing the values of existing keys, if
- * such keys are present.
- *
- * @return Returns the number of keys added to the map as a result of this call (not previously
- * present in the map). Values of existing keys are overwritten.
- */
- public int putAll(Iterable extends CharByteCursor> iterable);
-
- /**
- * If key
exists, putValue
is inserted into the map, otherwise any
- * existing value is incremented by additionValue
.
- *
- * @param key The key of the value to adjust.
- * @param putValue The value to put if key
does not exist.
- * @param incrementValue The value to add to the existing value if key
exists.
- * @return Returns the current value associated with key
(after changes).
- */
- public byte putOrAdd(char key, byte putValue, byte incrementValue);
-
- /**
- * An equivalent of calling
- *
- *
- * putOrAdd(key, additionValue, additionValue);
- *
- *
- * @param key The key of the value to adjust.
- * @param additionValue The value to put or add to the existing value if key
exists.
- * @return Returns the current value associated with key
(after changes).
- */
- public byte addTo(char key, byte additionValue);
-
- /**
- * Remove all values at the given key. The default value for the key type is returned if the value
- * does not exist in the map.
- */
- public byte remove(char key);
-
- /**
- * Compares the specified object with this set for equality. Returns {@code true} if and only if
- * the specified object is also a {@link CharByteMap} and both objects contains exactly the same
- * key-value pairs.
- */
- public boolean equals(Object obj);
-
- /**
- * @return A hash code of elements stored in the map. The hash code is defined as a sum of hash
- * codes of keys and values stored within the set). Because sum is commutative, this ensures
- * that different order of elements in a set does not affect the hash code.
- */
- public int hashCode();
-
- /**
- * Returns a logical "index" of a given key that can be used to speed up follow-up value setters
- * or getters in certain scenarios (conditional logic).
- *
- * true
if the index corresponds to an existing key or false
- * otherwise. This is equivalent to checking whether the index is a positive value (existing
- * keys) or a negative value (non-existing keys).
- */
- public boolean indexExists(int index);
-
- /**
- * Returns the value associated with an existing key.
- *
- * @see #indexOf
- * @param index The index of an existing key.
- * @return Returns the value currently associated with the key.
- * @throws AssertionError If assertions are enabled and the index does not correspond to an
- * existing key.
- */
- public byte indexGet(int index);
-
- /**
- * Replaces the value associated with an existing key and returns any previous value stored for
- * that key.
- *
- * @see #indexOf
- * @param index The index of an existing key.
- * @return Returns the previous value associated with the key.
- * @throws AssertionError If assertions are enabled and the index does not correspond to an
- * existing key.
- */
- public byte indexReplace(int index, byte newValue);
-
- /**
- * Inserts a key-value pair for a key that is not present in the map. This method may help in
- * avoiding double recalculation of the key's hash.
- *
- * @see #indexOf
- * @param index The index of a previously non-existing key, as returned from {@link #indexOf}.
- * @throws AssertionError If assertions are enabled and the index corresponds to an existing key.
- */
- public void indexInsert(int index, char key, byte value);
-
- /**
- * Removes a key-value pair at an index previously acquired from {@link #indexOf}.
- *
- * @see #indexOf
- * @param index The index of the key to remove, as returned from {@link #indexOf}.
- * @return Returns the previous value associated with the key.
- * @throws AssertionError If assertions are enabled and the index does not correspond to an
- * existing key.
- */
- public byte indexRemove(int index);
-
- /**
- * Clear all keys and values in the container.
- *
- * @see #release()
- */
- public void clear();
-
- /**
- * Removes all elements from the collection and additionally releases any internal buffers.
- * Typically, if the object is to be reused, a simple {@link #clear()} should be a better
- * alternative since it'll avoid reallocation.
- *
- * @see #clear()
- */
- public void release();
-
- /**
- * Visually depict the distribution of keys.
- *
- * @param characters The number of characters to "squeeze" the entire buffer into.
- * @return Returns a sequence of characters where '.' depicts an empty fragment of the internal
- * buffer and 'X' depicts full or nearly full capacity within the buffer's range and anything
- * between 1 and 9 is between.
- */
- public String visualizeKeyDistribution(int characters);
-}
diff --git a/sources/main/java/com/carrotsearch/hppc/CharCharAssociativeContainer.java b/sources/main/java/com/carrotsearch/hppc/CharCharAssociativeContainer.java
deleted file mode 100644
index b7334bbc..00000000
--- a/sources/main/java/com/carrotsearch/hppc/CharCharAssociativeContainer.java
+++ /dev/null
@@ -1,105 +0,0 @@
-package com.carrotsearch.hppc;
-
-import com.carrotsearch.hppc.cursors.*;
-import com.carrotsearch.hppc.predicates.*;
-import com.carrotsearch.hppc.procedures.*;
-import java.util.Iterator;
-
-/**
- * An associative container from keys to (one or possibly more) values.
- *
- * @see CharContainer
- */
-@com.carrotsearch.hppc.Generated(
- date = "2024-06-04T15:20:17+0200",
- value = "KTypeVTypeAssociativeContainer.java")
-public interface CharCharAssociativeContainer extends Iterable
- * for (IntShortCursor c : intShortMap) {
- * System.out.println("index=" + c.index + " key=" + c.key + " value=" + c.value);
- * }
- *
- * index
field inside the cursor gives the internal index inside the
- * container's implementation. The interpretation of this index depends on to the container.
- */
- @Override
- public Iteratortrue
if this container has an association to a value for the given key.
- */
- public boolean containsKey(char key);
-
- /**
- * @return Returns the current size (number of assigned keys) in the container.
- */
- public int size();
-
- /**
- * @return Return true
if this hash map contains no assigned keys.
- */
- public boolean isEmpty();
-
- /**
- * Removes all keys (and associated values) present in a given container. An alias to:
- *
- *
- * keys().removeAll(container)
- *
- *
- * but with no additional overhead.
- *
- * @return Returns the number of elements actually removed as a result of this call.
- */
- public int removeAll(CharContainer container);
-
- /**
- * Removes all keys (and associated values) for which the predicate returns true
.
- *
- * @return Returns the number of elements actually removed as a result of this call.
- */
- public int removeAll(CharPredicate predicate);
-
- /**
- * Removes all keys (and associated values) for which the predicate returns true
.
- *
- * @return Returns the number of elements actually removed as a result of this call.
- */
- public int removeAll(CharCharPredicate predicate);
-
- /**
- * Applies a given procedure to all keys-value pairs in this container. Returns the argument (any
- * subclass of {@link CharCharProcedure}. This lets the caller call methods of the argument by
- * chaining the call (even if the argument is an anonymous type) to retrieve computed values.
- */
- public true
.
- */
- public char
to char
, implemented using open addressing with
- * linear probing for collision resolution.
- *
- * @see HPPC interfaces diagram
- */
-@com.carrotsearch.hppc.Generated(
- date = "2024-06-04T15:20:16+0200",
- value = "KTypeVTypeHashMap.java")
-public class CharCharHashMap implements CharCharMap, Preallocable, Cloneable, Accountable {
-
- /** The array holding keys. */
- public char[] keys;
-
- /** The array holding values. */
- public char[] values;
-
- /**
- * The number of stored keys (assigned key slots), excluding the special "empty" key, if any (use
- * {@link #size()} instead).
- *
- * @see #size()
- */
- protected int assigned;
-
- /** Mask for slot scans in {@link #keys}. */
- protected int mask;
-
- /** Expand (rehash) {@link #keys} when {@link #assigned} hits this value. */
- protected int resizeAt;
-
- /** Special treatment for the "empty slot" key marker. */
- protected boolean hasEmptyKey;
-
- /** The load factor for {@link #keys}. */
- protected double loadFactor;
-
- /** Seed used to ensure the hash iteration order is different from an iteration to another. */
- protected int iterationSeed;
-
- /** New instance with sane defaults. */
- public CharCharHashMap() {
- this(DEFAULT_EXPECTED_ELEMENTS);
- }
-
- /**
- * New instance with sane defaults.
- *
- * @param expectedElements The expected number of elements guaranteed not to cause buffer
- * expansion (inclusive).
- */
- public CharCharHashMap(int expectedElements) {
- this(expectedElements, DEFAULT_LOAD_FACTOR);
- }
-
- /**
- * New instance with the provided defaults.
- *
- * @param expectedElements The expected number of elements guaranteed not to cause a rehash
- * (inclusive).
- * @param loadFactor The load factor for internal buffers. Insane load factors (zero, full
- * capacity) are rejected by {@link #verifyLoadFactor(double)}.
- */
- public CharCharHashMap(int expectedElements, double loadFactor) {
- this.loadFactor = verifyLoadFactor(loadFactor);
- iterationSeed = HashContainers.nextIterationSeed();
- ensureCapacity(expectedElements);
- }
-
- /** Create a hash map from all key-value pairs of another container. */
- public CharCharHashMap(CharCharAssociativeContainer container) {
- this(container.size());
- putAll(container);
- }
-
- /** {@inheritDoc} */
- @Override
- public char put(char key, char value) {
- assert assigned < mask + 1;
-
- final int mask = this.mask;
- if (((key) == 0)) {
- char previousValue = hasEmptyKey ? values[mask + 1] : ((char) 0);
- hasEmptyKey = true;
- values[mask + 1] = value;
- return previousValue;
- } else {
- final char[] keys = this.keys;
- int slot = hashKey(key) & mask;
-
- char existing;
- while (!((existing = keys[slot]) == 0)) {
- if (((key) == (existing))) {
- final char previousValue = values[slot];
- values[slot] = value;
- return previousValue;
- }
- slot = (slot + 1) & mask;
- }
-
- if (assigned == resizeAt) {
- allocateThenInsertThenRehash(slot, key, value);
- } else {
- keys[slot] = key;
- values[slot] = value;
- }
-
- assigned++;
- return ((char) 0);
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public int putAll(CharCharAssociativeContainer container) {
- final int count = size();
- for (CharCharCursor c : container) {
- put(c.key, c.value);
- }
- return size() - count;
- }
-
- /** Puts all key/value pairs from a given iterable into this map. */
- @Override
- public int putAll(Iterable extends CharCharCursor> iterable) {
- final int count = size();
- for (CharCharCursor c : iterable) {
- put(c.key, c.value);
- }
- return size() - count;
- }
-
- /**
- * If key
exists, putValue
is inserted into the map, otherwise any
- * existing value is incremented by additionValue
.
- *
- * @param key The key of the value to adjust.
- * @param putValue The value to put if key
does not exist.
- * @param incrementValue The value to add to the existing value if key
exists.
- * @return Returns the current value associated with key
(after changes).
- */
- @Override
- public char putOrAdd(char key, char putValue, char incrementValue) {
- assert assigned < mask + 1;
-
- int keyIndex = indexOf(key);
- if (indexExists(keyIndex)) {
- putValue = ((char) ((values[keyIndex]) + (incrementValue)));
- indexReplace(keyIndex, putValue);
- } else {
- indexInsert(keyIndex, key, putValue);
- }
- return putValue;
- }
-
- /**
- * Adds incrementValue
to any existing value for the given key
or
- * inserts incrementValue
if key
did not previously exist.
- *
- * @param key The key of the value to adjust.
- * @param incrementValue The value to put or add to the existing value if key
exists.
- * @return Returns the current value associated with key
(after changes).
- */
- @Override
- public char addTo(char key, char incrementValue) {
- return putOrAdd(key, incrementValue, incrementValue);
- }
-
- /** {@inheritDoc} */
- @Override
- public char remove(char key) {
- final int mask = this.mask;
- if (((key) == 0)) {
- if (!hasEmptyKey) {
- return ((char) 0);
- }
- hasEmptyKey = false;
- char previousValue = values[mask + 1];
- values[mask + 1] = ((char) 0);
- return previousValue;
- } else {
- final char[] keys = this.keys;
- int slot = hashKey(key) & mask;
-
- char existing;
- while (!((existing = keys[slot]) == 0)) {
- if (((key) == (existing))) {
- final char previousValue = values[slot];
- shiftConflictingKeys(slot);
- return previousValue;
- }
- slot = (slot + 1) & mask;
- }
-
- return ((char) 0);
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public int removeAll(CharContainer other) {
- final int before = size();
-
- // Try to iterate over the smaller set of values or
- // over the container that isn't implementing
- // efficient contains() lookup.
-
- if (other.size() >= size() && other instanceof CharLookupContainer) {
- if (hasEmptyKey && other.contains(((char) 0))) {
- hasEmptyKey = false;
- values[mask + 1] = ((char) 0);
- }
-
- final char[] keys = this.keys;
- for (int slot = 0, max = this.mask; slot <= max; ) {
- char existing;
- if (!((existing = keys[slot]) == 0) && other.contains(existing)) {
- // Shift, do not increment slot.
- shiftConflictingKeys(slot);
- } else {
- slot++;
- }
- }
- } else {
- for (CharCursor c : other) {
- remove(c.value);
- }
- }
-
- return before - size();
- }
-
- /** {@inheritDoc} */
- @Override
- public int removeAll(CharCharPredicate predicate) {
- final int before = size();
-
- final int mask = this.mask;
-
- if (hasEmptyKey) {
- if (predicate.apply(((char) 0), values[mask + 1])) {
- hasEmptyKey = false;
- values[mask + 1] = ((char) 0);
- }
- }
-
- final char[] keys = this.keys;
- final char[] values = this.values;
- for (int slot = 0; slot <= mask; ) {
- char existing;
- if (!((existing = keys[slot]) == 0) && predicate.apply(existing, values[slot])) {
- // Shift, do not increment slot.
- shiftConflictingKeys(slot);
- } else {
- slot++;
- }
- }
-
- return before - size();
- }
-
- /** {@inheritDoc} */
- @Override
- public int removeAll(CharPredicate predicate) {
- final int before = size();
-
- if (hasEmptyKey) {
- if (predicate.apply(((char) 0))) {
- hasEmptyKey = false;
- values[mask + 1] = ((char) 0);
- }
- }
-
- final char[] keys = this.keys;
- for (int slot = 0, max = this.mask; slot <= max; ) {
- char existing;
- if (!((existing = keys[slot]) == 0) && predicate.apply(existing)) {
- // Shift, do not increment slot.
- shiftConflictingKeys(slot);
- } else {
- slot++;
- }
- }
-
- return before - size();
- }
-
- /** {@inheritDoc} */
- @Override
- public char get(char key) {
- if (((key) == 0)) {
- return hasEmptyKey ? values[mask + 1] : ((char) 0);
- } else {
- final char[] keys = this.keys;
- final int mask = this.mask;
- int slot = hashKey(key) & mask;
-
- char existing;
- while (!((existing = keys[slot]) == 0)) {
- if (((key) == (existing))) {
- return values[slot];
- }
- slot = (slot + 1) & mask;
- }
-
- return ((char) 0);
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public char getOrDefault(char key, char defaultValue) {
- if (((key) == 0)) {
- return hasEmptyKey ? values[mask + 1] : defaultValue;
- } else {
- final char[] keys = this.keys;
- final int mask = this.mask;
- int slot = hashKey(key) & mask;
-
- char existing;
- while (!((existing = keys[slot]) == 0)) {
- if (((key) == (existing))) {
- return values[slot];
- }
- slot = (slot + 1) & mask;
- }
-
- return defaultValue;
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean containsKey(char key) {
- if (((key) == 0)) {
- return hasEmptyKey;
- } else {
- final char[] keys = this.keys;
- final int mask = this.mask;
- int slot = hashKey(key) & mask;
-
- char existing;
- while (!((existing = keys[slot]) == 0)) {
- if (((key) == (existing))) {
- return true;
- }
- slot = (slot + 1) & mask;
- }
-
- return false;
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public int indexOf(char key) {
- final int mask = this.mask;
- if (((key) == 0)) {
- return hasEmptyKey ? mask + 1 : ~(mask + 1);
- } else {
- final char[] keys = this.keys;
- int slot = hashKey(key) & mask;
-
- char existing;
- while (!((existing = keys[slot]) == 0)) {
- if (((key) == (existing))) {
- return slot;
- }
- slot = (slot + 1) & mask;
- }
-
- return ~slot;
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean indexExists(int index) {
- assert index < 0 || (index >= 0 && index <= mask) || (index == mask + 1 && hasEmptyKey);
-
- return index >= 0;
- }
-
- /** {@inheritDoc} */
- @Override
- public char indexGet(int index) {
- assert index >= 0 : "The index must point at an existing key.";
- assert index <= mask || (index == mask + 1 && hasEmptyKey);
-
- return values[index];
- }
-
- /** {@inheritDoc} */
- @Override
- public char indexReplace(int index, char newValue) {
- assert index >= 0 : "The index must point at an existing key.";
- assert index <= mask || (index == mask + 1 && hasEmptyKey);
-
- char previousValue = values[index];
- values[index] = newValue;
- return previousValue;
- }
-
- /** {@inheritDoc} */
- @Override
- public void indexInsert(int index, char key, char value) {
- assert index < 0 : "The index must not point at an existing key.";
-
- index = ~index;
- if (((key) == 0)) {
- assert index == mask + 1;
- values[index] = value;
- hasEmptyKey = true;
- } else {
- assert ((keys[index]) == 0);
-
- if (assigned == resizeAt) {
- allocateThenInsertThenRehash(index, key, value);
- } else {
- keys[index] = key;
- values[index] = value;
- }
-
- assigned++;
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public char indexRemove(int index) {
- assert index >= 0 : "The index must point at an existing key.";
- assert index <= mask || (index == mask + 1 && hasEmptyKey);
-
- char previousValue = values[index];
- if (index > mask) {
- assert index == mask + 1;
- hasEmptyKey = false;
- values[index] = ((char) 0);
- } else {
- shiftConflictingKeys(index);
- }
- return previousValue;
- }
-
- /** {@inheritDoc} */
- @Override
- public void clear() {
- assigned = 0;
- hasEmptyKey = false;
-
- Arrays.fill(keys, ((char) 0));
- }
-
- /** {@inheritDoc} */
- @Override
- public void release() {
- assigned = 0;
- hasEmptyKey = false;
-
- keys = null;
- values = null;
- ensureCapacity(Containers.DEFAULT_EXPECTED_ELEMENTS);
- }
-
- /** {@inheritDoc} */
- @Override
- public int size() {
- return assigned + (hasEmptyKey ? 1 : 0);
- }
-
- /** {@inheritDoc} */
- public boolean isEmpty() {
- return size() == 0;
- }
-
- /** {@inheritDoc} */
- @Override
- public int hashCode() {
- int h = hasEmptyKey ? 0xDEADBEEF : 0;
- for (CharCharCursor c : this) {
- h += BitMixer.mix(c.key) + BitMixer.mix(c.value);
- }
- return h;
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean equals(Object obj) {
- return (this == obj)
- || (obj != null && getClass() == obj.getClass() && equalElements(getClass().cast(obj)));
- }
-
- /** Return true if all keys of some other container exist in this container. */
- protected boolean equalElements(CharCharHashMap other) {
- if (other.size() != size()) {
- return false;
- }
-
- for (CharCharCursor c : other) {
- char key = c.key;
- if (!containsKey(key) || !((c.value) == (get(key)))) {
- return false;
- }
- }
-
- return true;
- }
-
- /**
- * Ensure this container can hold at least the given number of keys (entries) without resizing its
- * buffers.
- *
- * @param expectedElements The total number of keys, inclusive.
- */
- @Override
- public void ensureCapacity(int expectedElements) {
- if (expectedElements > resizeAt || keys == null) {
- final char[] prevKeys = this.keys;
- final char[] prevValues = this.values;
- allocateBuffers(minBufferSize(expectedElements, loadFactor));
- if (prevKeys != null && !isEmpty()) {
- rehash(prevKeys, prevValues);
- }
- }
- }
-
- @Override
- public long ramBytesAllocated() {
- // int: iterationSeed, assigned, mask, resizeAt
- // double: loadFactor
- // boolean: hasEmptyKey
- return RamUsageEstimator.NUM_BYTES_OBJECT_HEADER
- + 4 * Integer.BYTES
- + Double.BYTES
- + 1
- + RamUsageEstimator.shallowSizeOfArray(keys)
- + RamUsageEstimator.shallowSizeOfArray(values);
- }
-
- @Override
- public long ramBytesUsed() {
- // int: iterationSeed, assigned, mask, resizeAt
- // double: loadFactor
- // boolean: hasEmptyKey
- return RamUsageEstimator.NUM_BYTES_OBJECT_HEADER
- + 4 * Integer.BYTES
- + Double.BYTES
- + 1
- + RamUsageEstimator.shallowUsedSizeOfArray(keys, size())
- + RamUsageEstimator.shallowUsedSizeOfArray(values, size());
- }
-
- /**
- * Provides the next iteration seed used to build the iteration starting slot and offset
- * increment. This method does not need to be synchronized, what matters is that each thread gets
- * a sequence of varying seeds.
- */
- protected int nextIterationSeed() {
- return iterationSeed = BitMixer.mixPhi(iterationSeed);
- }
-
- /** An iterator implementation for {@link #iterator}. */
- private final class EntryIterator extends AbstractIteratorslot
.
- */
- protected void shiftConflictingKeys(int gapSlot) {
- final char[] keys = this.keys;
- final char[] values = this.values;
- final int mask = this.mask;
-
- // Perform shifts of conflicting keys to fill in the gap.
- int distance = 0;
- while (true) {
- final int slot = (gapSlot + (++distance)) & mask;
- final char existing = keys[slot];
- if (((existing) == 0)) {
- break;
- }
-
- final int idealSlot = hashKey(existing);
- final int shift = (slot - idealSlot) & mask;
- if (shift >= distance) {
- // Entry at this position was originally at or before the gap slot.
- // Move the conflict-shifted entry to the gap's position and repeat the procedure
- // for any entries to the right of the current position, treating it
- // as the new gap.
- keys[gapSlot] = existing;
- values[gapSlot] = values[slot];
- gapSlot = slot;
- distance = 0;
- }
- }
-
- // Mark the last found gap slot without a conflict as empty.
- keys[gapSlot] = ((char) 0);
- values[gapSlot] = ((char) 0);
- assigned--;
- }
-}
diff --git a/sources/main/java/com/carrotsearch/hppc/CharCharMap.java b/sources/main/java/com/carrotsearch/hppc/CharCharMap.java
deleted file mode 100644
index c3690bba..00000000
--- a/sources/main/java/com/carrotsearch/hppc/CharCharMap.java
+++ /dev/null
@@ -1,205 +0,0 @@
-package com.carrotsearch.hppc;
-
-import com.carrotsearch.hppc.cursors.CharCharCursor;
-
-/** An associative container with unique binding from keys to a single value. */
-@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeVTypeMap.java")
-public interface CharCharMap extends CharCharAssociativeContainer {
- /**
- * @return Returns the value associated with the given key or the default value for the value
- * type, if the key is not associated with any value. For numeric value types, this default
- * value is 0, for object types it is {@code null}.
- */
- public char get(char key);
-
- /**
- * @return Returns the value associated with the given key or the provided default value if the
- * key is not associated with any value.
- */
- public char getOrDefault(char key, char defaultValue);
-
- /**
- * Place a given key and value in the container.
- *
- * @return The value previously stored under the given key in the map is returned.
- */
- public char put(char key, char value);
-
- /**
- * If the specified key is not already associated with a value, associates it with the given
- * value.
- *
- * @return {@code true} if {@code key} did not exist and {@code value} was placed in the map,
- * {@code false} otherwise.
- */
- public default boolean putIfAbsent(char key, char value) {
- int keyIndex = indexOf(key);
- if (indexExists(keyIndex)) {
- return false;
- } else {
- indexInsert(keyIndex, key, value);
- return true;
- }
- }
-
- /**
- * Puts all keys from another container to this map, replacing the values of existing keys, if
- * such keys are present.
- *
- * @return Returns the number of keys added to the map as a result of this call (not previously
- * present in the map). Values of existing keys are overwritten.
- */
- public int putAll(CharCharAssociativeContainer container);
-
- /**
- * Puts all keys from an iterable cursor to this map, replacing the values of existing keys, if
- * such keys are present.
- *
- * @return Returns the number of keys added to the map as a result of this call (not previously
- * present in the map). Values of existing keys are overwritten.
- */
- public int putAll(Iterable extends CharCharCursor> iterable);
-
- /**
- * If key
exists, putValue
is inserted into the map, otherwise any
- * existing value is incremented by additionValue
.
- *
- * @param key The key of the value to adjust.
- * @param putValue The value to put if key
does not exist.
- * @param incrementValue The value to add to the existing value if key
exists.
- * @return Returns the current value associated with key
(after changes).
- */
- public char putOrAdd(char key, char putValue, char incrementValue);
-
- /**
- * An equivalent of calling
- *
- *
- * putOrAdd(key, additionValue, additionValue);
- *
- *
- * @param key The key of the value to adjust.
- * @param additionValue The value to put or add to the existing value if key
exists.
- * @return Returns the current value associated with key
(after changes).
- */
- public char addTo(char key, char additionValue);
-
- /**
- * Remove all values at the given key. The default value for the key type is returned if the value
- * does not exist in the map.
- */
- public char remove(char key);
-
- /**
- * Compares the specified object with this set for equality. Returns {@code true} if and only if
- * the specified object is also a {@link CharCharMap} and both objects contains exactly the same
- * key-value pairs.
- */
- public boolean equals(Object obj);
-
- /**
- * @return A hash code of elements stored in the map. The hash code is defined as a sum of hash
- * codes of keys and values stored within the set). Because sum is commutative, this ensures
- * that different order of elements in a set does not affect the hash code.
- */
- public int hashCode();
-
- /**
- * Returns a logical "index" of a given key that can be used to speed up follow-up value setters
- * or getters in certain scenarios (conditional logic).
- *
- * true
if the index corresponds to an existing key or false
- * otherwise. This is equivalent to checking whether the index is a positive value (existing
- * keys) or a negative value (non-existing keys).
- */
- public boolean indexExists(int index);
-
- /**
- * Returns the value associated with an existing key.
- *
- * @see #indexOf
- * @param index The index of an existing key.
- * @return Returns the value currently associated with the key.
- * @throws AssertionError If assertions are enabled and the index does not correspond to an
- * existing key.
- */
- public char indexGet(int index);
-
- /**
- * Replaces the value associated with an existing key and returns any previous value stored for
- * that key.
- *
- * @see #indexOf
- * @param index The index of an existing key.
- * @return Returns the previous value associated with the key.
- * @throws AssertionError If assertions are enabled and the index does not correspond to an
- * existing key.
- */
- public char indexReplace(int index, char newValue);
-
- /**
- * Inserts a key-value pair for a key that is not present in the map. This method may help in
- * avoiding double recalculation of the key's hash.
- *
- * @see #indexOf
- * @param index The index of a previously non-existing key, as returned from {@link #indexOf}.
- * @throws AssertionError If assertions are enabled and the index corresponds to an existing key.
- */
- public void indexInsert(int index, char key, char value);
-
- /**
- * Removes a key-value pair at an index previously acquired from {@link #indexOf}.
- *
- * @see #indexOf
- * @param index The index of the key to remove, as returned from {@link #indexOf}.
- * @return Returns the previous value associated with the key.
- * @throws AssertionError If assertions are enabled and the index does not correspond to an
- * existing key.
- */
- public char indexRemove(int index);
-
- /**
- * Clear all keys and values in the container.
- *
- * @see #release()
- */
- public void clear();
-
- /**
- * Removes all elements from the collection and additionally releases any internal buffers.
- * Typically, if the object is to be reused, a simple {@link #clear()} should be a better
- * alternative since it'll avoid reallocation.
- *
- * @see #clear()
- */
- public void release();
-
- /**
- * Visually depict the distribution of keys.
- *
- * @param characters The number of characters to "squeeze" the entire buffer into.
- * @return Returns a sequence of characters where '.' depicts an empty fragment of the internal
- * buffer and 'X' depicts full or nearly full capacity within the buffer's range and anything
- * between 1 and 9 is between.
- */
- public String visualizeKeyDistribution(int characters);
-}
diff --git a/sources/main/java/com/carrotsearch/hppc/CharCollection.java b/sources/main/java/com/carrotsearch/hppc/CharCollection.java
deleted file mode 100644
index 4cc8517b..00000000
--- a/sources/main/java/com/carrotsearch/hppc/CharCollection.java
+++ /dev/null
@@ -1,64 +0,0 @@
-package com.carrotsearch.hppc;
-
-import com.carrotsearch.hppc.predicates.CharPredicate;
-
-/**
- * A collection allows basic, efficient operations on sets of elements (difference and
- * intersection).
- */
-@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeCollection.java")
-public interface CharCollection extends CharContainer {
- /**
- * Removes all occurrences of e
from this collection.
- *
- * @param e Element to be removed from this collection, if present.
- * @return The number of removed elements as a result of this call.
- */
- public int removeAll(char e);
-
- /**
- * Removes all elements in this collection that are present in c
.
- *
- * @return Returns the number of removed elements.
- */
- public int removeAll(CharLookupContainer c);
-
- /**
- * Removes all elements in this collection for which the given predicate returns true
- * .
- *
- * @return Returns the number of removed elements.
- */
- public int removeAll(CharPredicate predicate);
-
- /**
- * Keeps all elements in this collection that are present in c
. Runs in time
- * proportional to the number of elements in this collection. Equivalent of sets intersection.
- *
- * @return Returns the number of removed elements.
- */
- public int retainAll(CharLookupContainer c);
-
- /**
- * Keeps all elements in this collection for which the given predicate returns true
.
- *
- * @return Returns the number of removed elements.
- */
- public int retainAll(CharPredicate predicate);
-
- /**
- * Removes all elements from this collection.
- *
- * @see #release()
- */
- public void clear();
-
- /**
- * Removes all elements from the collection and additionally releases any internal buffers.
- * Typically, if the object is to be reused, a simple {@link #clear()} should be a better
- * alternative since it'll avoid reallocation.
- *
- * @see #clear()
- */
- public void release();
-}
diff --git a/sources/main/java/com/carrotsearch/hppc/CharContainer.java b/sources/main/java/com/carrotsearch/hppc/CharContainer.java
deleted file mode 100644
index 5977583b..00000000
--- a/sources/main/java/com/carrotsearch/hppc/CharContainer.java
+++ /dev/null
@@ -1,76 +0,0 @@
-package com.carrotsearch.hppc;
-
-import com.carrotsearch.hppc.cursors.CharCursor;
-import com.carrotsearch.hppc.predicates.CharPredicate;
-import com.carrotsearch.hppc.procedures.CharProcedure;
-import java.util.Iterator;
-
-/** A generic container holding char
s. */
-@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeContainer.java")
-public interface CharContainer extends Iterable
- * for (CharCursor<char> c : container) {
- * System.out.println("index=" + c.index + " value=" + c.value);
- * }
- *
- */
- public Iteratortrue
if this container has an element equal to e
.
- */
- public boolean contains(char e);
-
- /**
- * Return the current number of elements in this container. The time for calculating the
- * container's size may take O(n)
time, although implementing classes should try to
- * maintain the current size and return in constant time.
- */
- public int size();
-
- /** Shortcut for size() == 0
. */
- public boolean isEmpty();
-
- /**
- * Copies all elements of this container to an array.
- *
- * procedure
to all container elements. Returns the argument (any subclass
- * of {@link CharProcedure}. This lets the caller to call methods of the argument by chaining the
- * call (even if the argument is an anonymous type) to retrieve computed values, for example
- * (IntContainer):
- *
- *
- * int count = container.forEach(new IntProcedure() {
- * int count; // this is a field declaration in an anonymous class.
- *
- * public void apply(int value) {
- * count++;
- * }
- * }).count;
- *
- */
- public predicate
to container elements as long, as the predicate returns
- * true
. The iteration is interrupted otherwise.
- */
- public e
.
- *
- * @return The deleted element's index or -1
if the element was not found.
- */
- public int removeFirst(char e);
-
- /**
- * Removes the last element that equals e
.
- *
- * @return The deleted element's index or -1
if the element was not found.
- */
- public int removeLast(char e);
-
- /** Inserts the specified element at the front of this deque. */
- public void addFirst(char e);
-
- /** Inserts the specified element at the end of this deque. */
- public void addLast(char e);
-
- /**
- * Retrieves and removes the first element of this deque.
- *
- * @return the head (first) element of this deque.
- */
- public char removeFirst();
-
- /**
- * Retrieves and removes the last element of this deque.
- *
- * @return the tail of this deque.
- */
- public char removeLast();
-
- /**
- * Retrieves the first element of this deque but does not remove it.
- *
- * @return the head of this deque.
- */
- public char getFirst();
-
- /**
- * Retrieves the last element of this deque but does not remove it.
- *
- * @return the head of this deque.
- */
- public char getLast();
-
- /**
- * @return An iterator over elements in this deque in tail-to-head order.
- */
- public Iteratorprocedure
to all elements in tail-to-head order. */
- public predicate
to container elements as long, as the predicate returns
- * true
. The iteration is interrupted otherwise.
- */
- public
- * for (IntShortCursor c : intShortMap) {
- * System.out.println("index=" + c.index + " key=" + c.key + " value=" + c.value);
- * }
- *
- * index
field inside the cursor gives the internal index inside the
- * container's implementation. The interpretation of this index depends on to the container.
- */
- @Override
- public Iteratortrue
if this container has an association to a value for the given key.
- */
- public boolean containsKey(char key);
-
- /**
- * @return Returns the current size (number of assigned keys) in the container.
- */
- public int size();
-
- /**
- * @return Return true
if this hash map contains no assigned keys.
- */
- public boolean isEmpty();
-
- /**
- * Removes all keys (and associated values) present in a given container. An alias to:
- *
- *
- * keys().removeAll(container)
- *
- *
- * but with no additional overhead.
- *
- * @return Returns the number of elements actually removed as a result of this call.
- */
- public int removeAll(CharContainer container);
-
- /**
- * Removes all keys (and associated values) for which the predicate returns true
.
- *
- * @return Returns the number of elements actually removed as a result of this call.
- */
- public int removeAll(CharPredicate predicate);
-
- /**
- * Removes all keys (and associated values) for which the predicate returns true
.
- *
- * @return Returns the number of elements actually removed as a result of this call.
- */
- public int removeAll(CharDoublePredicate predicate);
-
- /**
- * Applies a given procedure to all keys-value pairs in this container. Returns the argument (any
- * subclass of {@link CharDoubleProcedure}. This lets the caller call methods of the argument by
- * chaining the call (even if the argument is an anonymous type) to retrieve computed values.
- */
- public true
.
- */
- public char
to double
, implemented using open addressing with
- * linear probing for collision resolution.
- *
- * @see HPPC interfaces diagram
- */
-@com.carrotsearch.hppc.Generated(
- date = "2024-06-04T15:20:16+0200",
- value = "KTypeVTypeHashMap.java")
-public class CharDoubleHashMap implements CharDoubleMap, Preallocable, Cloneable, Accountable {
-
- /** The array holding keys. */
- public char[] keys;
-
- /** The array holding values. */
- public double[] values;
-
- /**
- * The number of stored keys (assigned key slots), excluding the special "empty" key, if any (use
- * {@link #size()} instead).
- *
- * @see #size()
- */
- protected int assigned;
-
- /** Mask for slot scans in {@link #keys}. */
- protected int mask;
-
- /** Expand (rehash) {@link #keys} when {@link #assigned} hits this value. */
- protected int resizeAt;
-
- /** Special treatment for the "empty slot" key marker. */
- protected boolean hasEmptyKey;
-
- /** The load factor for {@link #keys}. */
- protected double loadFactor;
-
- /** Seed used to ensure the hash iteration order is different from an iteration to another. */
- protected int iterationSeed;
-
- /** New instance with sane defaults. */
- public CharDoubleHashMap() {
- this(DEFAULT_EXPECTED_ELEMENTS);
- }
-
- /**
- * New instance with sane defaults.
- *
- * @param expectedElements The expected number of elements guaranteed not to cause buffer
- * expansion (inclusive).
- */
- public CharDoubleHashMap(int expectedElements) {
- this(expectedElements, DEFAULT_LOAD_FACTOR);
- }
-
- /**
- * New instance with the provided defaults.
- *
- * @param expectedElements The expected number of elements guaranteed not to cause a rehash
- * (inclusive).
- * @param loadFactor The load factor for internal buffers. Insane load factors (zero, full
- * capacity) are rejected by {@link #verifyLoadFactor(double)}.
- */
- public CharDoubleHashMap(int expectedElements, double loadFactor) {
- this.loadFactor = verifyLoadFactor(loadFactor);
- iterationSeed = HashContainers.nextIterationSeed();
- ensureCapacity(expectedElements);
- }
-
- /** Create a hash map from all key-value pairs of another container. */
- public CharDoubleHashMap(CharDoubleAssociativeContainer container) {
- this(container.size());
- putAll(container);
- }
-
- /** {@inheritDoc} */
- @Override
- public double put(char key, double value) {
- assert assigned < mask + 1;
-
- final int mask = this.mask;
- if (((key) == 0)) {
- double previousValue = hasEmptyKey ? values[mask + 1] : 0d;
- hasEmptyKey = true;
- values[mask + 1] = value;
- return previousValue;
- } else {
- final char[] keys = this.keys;
- int slot = hashKey(key) & mask;
-
- char existing;
- while (!((existing = keys[slot]) == 0)) {
- if (((key) == (existing))) {
- final double previousValue = values[slot];
- values[slot] = value;
- return previousValue;
- }
- slot = (slot + 1) & mask;
- }
-
- if (assigned == resizeAt) {
- allocateThenInsertThenRehash(slot, key, value);
- } else {
- keys[slot] = key;
- values[slot] = value;
- }
-
- assigned++;
- return 0d;
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public int putAll(CharDoubleAssociativeContainer container) {
- final int count = size();
- for (CharDoubleCursor c : container) {
- put(c.key, c.value);
- }
- return size() - count;
- }
-
- /** Puts all key/value pairs from a given iterable into this map. */
- @Override
- public int putAll(Iterable extends CharDoubleCursor> iterable) {
- final int count = size();
- for (CharDoubleCursor c : iterable) {
- put(c.key, c.value);
- }
- return size() - count;
- }
-
- /**
- * If key
exists, putValue
is inserted into the map, otherwise any
- * existing value is incremented by additionValue
.
- *
- * @param key The key of the value to adjust.
- * @param putValue The value to put if key
does not exist.
- * @param incrementValue The value to add to the existing value if key
exists.
- * @return Returns the current value associated with key
(after changes).
- */
- @Override
- public double putOrAdd(char key, double putValue, double incrementValue) {
- assert assigned < mask + 1;
-
- int keyIndex = indexOf(key);
- if (indexExists(keyIndex)) {
- putValue = ((double) ((values[keyIndex]) + (incrementValue)));
- indexReplace(keyIndex, putValue);
- } else {
- indexInsert(keyIndex, key, putValue);
- }
- return putValue;
- }
-
- /**
- * Adds incrementValue
to any existing value for the given key
or
- * inserts incrementValue
if key
did not previously exist.
- *
- * @param key The key of the value to adjust.
- * @param incrementValue The value to put or add to the existing value if key
exists.
- * @return Returns the current value associated with key
(after changes).
- */
- @Override
- public double addTo(char key, double incrementValue) {
- return putOrAdd(key, incrementValue, incrementValue);
- }
-
- /** {@inheritDoc} */
- @Override
- public double remove(char key) {
- final int mask = this.mask;
- if (((key) == 0)) {
- if (!hasEmptyKey) {
- return 0d;
- }
- hasEmptyKey = false;
- double previousValue = values[mask + 1];
- values[mask + 1] = 0d;
- return previousValue;
- } else {
- final char[] keys = this.keys;
- int slot = hashKey(key) & mask;
-
- char existing;
- while (!((existing = keys[slot]) == 0)) {
- if (((key) == (existing))) {
- final double previousValue = values[slot];
- shiftConflictingKeys(slot);
- return previousValue;
- }
- slot = (slot + 1) & mask;
- }
-
- return 0d;
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public int removeAll(CharContainer other) {
- final int before = size();
-
- // Try to iterate over the smaller set of values or
- // over the container that isn't implementing
- // efficient contains() lookup.
-
- if (other.size() >= size() && other instanceof CharLookupContainer) {
- if (hasEmptyKey && other.contains(((char) 0))) {
- hasEmptyKey = false;
- values[mask + 1] = 0d;
- }
-
- final char[] keys = this.keys;
- for (int slot = 0, max = this.mask; slot <= max; ) {
- char existing;
- if (!((existing = keys[slot]) == 0) && other.contains(existing)) {
- // Shift, do not increment slot.
- shiftConflictingKeys(slot);
- } else {
- slot++;
- }
- }
- } else {
- for (CharCursor c : other) {
- remove(c.value);
- }
- }
-
- return before - size();
- }
-
- /** {@inheritDoc} */
- @Override
- public int removeAll(CharDoublePredicate predicate) {
- final int before = size();
-
- final int mask = this.mask;
-
- if (hasEmptyKey) {
- if (predicate.apply(((char) 0), values[mask + 1])) {
- hasEmptyKey = false;
- values[mask + 1] = 0d;
- }
- }
-
- final char[] keys = this.keys;
- final double[] values = this.values;
- for (int slot = 0; slot <= mask; ) {
- char existing;
- if (!((existing = keys[slot]) == 0) && predicate.apply(existing, values[slot])) {
- // Shift, do not increment slot.
- shiftConflictingKeys(slot);
- } else {
- slot++;
- }
- }
-
- return before - size();
- }
-
- /** {@inheritDoc} */
- @Override
- public int removeAll(CharPredicate predicate) {
- final int before = size();
-
- if (hasEmptyKey) {
- if (predicate.apply(((char) 0))) {
- hasEmptyKey = false;
- values[mask + 1] = 0d;
- }
- }
-
- final char[] keys = this.keys;
- for (int slot = 0, max = this.mask; slot <= max; ) {
- char existing;
- if (!((existing = keys[slot]) == 0) && predicate.apply(existing)) {
- // Shift, do not increment slot.
- shiftConflictingKeys(slot);
- } else {
- slot++;
- }
- }
-
- return before - size();
- }
-
- /** {@inheritDoc} */
- @Override
- public double get(char key) {
- if (((key) == 0)) {
- return hasEmptyKey ? values[mask + 1] : 0d;
- } else {
- final char[] keys = this.keys;
- final int mask = this.mask;
- int slot = hashKey(key) & mask;
-
- char existing;
- while (!((existing = keys[slot]) == 0)) {
- if (((key) == (existing))) {
- return values[slot];
- }
- slot = (slot + 1) & mask;
- }
-
- return 0d;
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public double getOrDefault(char key, double defaultValue) {
- if (((key) == 0)) {
- return hasEmptyKey ? values[mask + 1] : defaultValue;
- } else {
- final char[] keys = this.keys;
- final int mask = this.mask;
- int slot = hashKey(key) & mask;
-
- char existing;
- while (!((existing = keys[slot]) == 0)) {
- if (((key) == (existing))) {
- return values[slot];
- }
- slot = (slot + 1) & mask;
- }
-
- return defaultValue;
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean containsKey(char key) {
- if (((key) == 0)) {
- return hasEmptyKey;
- } else {
- final char[] keys = this.keys;
- final int mask = this.mask;
- int slot = hashKey(key) & mask;
-
- char existing;
- while (!((existing = keys[slot]) == 0)) {
- if (((key) == (existing))) {
- return true;
- }
- slot = (slot + 1) & mask;
- }
-
- return false;
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public int indexOf(char key) {
- final int mask = this.mask;
- if (((key) == 0)) {
- return hasEmptyKey ? mask + 1 : ~(mask + 1);
- } else {
- final char[] keys = this.keys;
- int slot = hashKey(key) & mask;
-
- char existing;
- while (!((existing = keys[slot]) == 0)) {
- if (((key) == (existing))) {
- return slot;
- }
- slot = (slot + 1) & mask;
- }
-
- return ~slot;
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean indexExists(int index) {
- assert index < 0 || (index >= 0 && index <= mask) || (index == mask + 1 && hasEmptyKey);
-
- return index >= 0;
- }
-
- /** {@inheritDoc} */
- @Override
- public double indexGet(int index) {
- assert index >= 0 : "The index must point at an existing key.";
- assert index <= mask || (index == mask + 1 && hasEmptyKey);
-
- return values[index];
- }
-
- /** {@inheritDoc} */
- @Override
- public double indexReplace(int index, double newValue) {
- assert index >= 0 : "The index must point at an existing key.";
- assert index <= mask || (index == mask + 1 && hasEmptyKey);
-
- double previousValue = values[index];
- values[index] = newValue;
- return previousValue;
- }
-
- /** {@inheritDoc} */
- @Override
- public void indexInsert(int index, char key, double value) {
- assert index < 0 : "The index must not point at an existing key.";
-
- index = ~index;
- if (((key) == 0)) {
- assert index == mask + 1;
- values[index] = value;
- hasEmptyKey = true;
- } else {
- assert ((keys[index]) == 0);
-
- if (assigned == resizeAt) {
- allocateThenInsertThenRehash(index, key, value);
- } else {
- keys[index] = key;
- values[index] = value;
- }
-
- assigned++;
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public double indexRemove(int index) {
- assert index >= 0 : "The index must point at an existing key.";
- assert index <= mask || (index == mask + 1 && hasEmptyKey);
-
- double previousValue = values[index];
- if (index > mask) {
- assert index == mask + 1;
- hasEmptyKey = false;
- values[index] = 0d;
- } else {
- shiftConflictingKeys(index);
- }
- return previousValue;
- }
-
- /** {@inheritDoc} */
- @Override
- public void clear() {
- assigned = 0;
- hasEmptyKey = false;
-
- Arrays.fill(keys, ((char) 0));
- }
-
- /** {@inheritDoc} */
- @Override
- public void release() {
- assigned = 0;
- hasEmptyKey = false;
-
- keys = null;
- values = null;
- ensureCapacity(Containers.DEFAULT_EXPECTED_ELEMENTS);
- }
-
- /** {@inheritDoc} */
- @Override
- public int size() {
- return assigned + (hasEmptyKey ? 1 : 0);
- }
-
- /** {@inheritDoc} */
- public boolean isEmpty() {
- return size() == 0;
- }
-
- /** {@inheritDoc} */
- @Override
- public int hashCode() {
- int h = hasEmptyKey ? 0xDEADBEEF : 0;
- for (CharDoubleCursor c : this) {
- h += BitMixer.mix(c.key) + BitMixer.mix(c.value);
- }
- return h;
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean equals(Object obj) {
- return (this == obj)
- || (obj != null && getClass() == obj.getClass() && equalElements(getClass().cast(obj)));
- }
-
- /** Return true if all keys of some other container exist in this container. */
- protected boolean equalElements(CharDoubleHashMap other) {
- if (other.size() != size()) {
- return false;
- }
-
- for (CharDoubleCursor c : other) {
- char key = c.key;
- if (!containsKey(key)
- || !(Double.doubleToLongBits(c.value) == Double.doubleToLongBits(get(key)))) {
- return false;
- }
- }
-
- return true;
- }
-
- /**
- * Ensure this container can hold at least the given number of keys (entries) without resizing its
- * buffers.
- *
- * @param expectedElements The total number of keys, inclusive.
- */
- @Override
- public void ensureCapacity(int expectedElements) {
- if (expectedElements > resizeAt || keys == null) {
- final char[] prevKeys = this.keys;
- final double[] prevValues = this.values;
- allocateBuffers(minBufferSize(expectedElements, loadFactor));
- if (prevKeys != null && !isEmpty()) {
- rehash(prevKeys, prevValues);
- }
- }
- }
-
- @Override
- public long ramBytesAllocated() {
- // int: iterationSeed, assigned, mask, resizeAt
- // double: loadFactor
- // boolean: hasEmptyKey
- return RamUsageEstimator.NUM_BYTES_OBJECT_HEADER
- + 4 * Integer.BYTES
- + Double.BYTES
- + 1
- + RamUsageEstimator.shallowSizeOfArray(keys)
- + RamUsageEstimator.shallowSizeOfArray(values);
- }
-
- @Override
- public long ramBytesUsed() {
- // int: iterationSeed, assigned, mask, resizeAt
- // double: loadFactor
- // boolean: hasEmptyKey
- return RamUsageEstimator.NUM_BYTES_OBJECT_HEADER
- + 4 * Integer.BYTES
- + Double.BYTES
- + 1
- + RamUsageEstimator.shallowUsedSizeOfArray(keys, size())
- + RamUsageEstimator.shallowUsedSizeOfArray(values, size());
- }
-
- /**
- * Provides the next iteration seed used to build the iteration starting slot and offset
- * increment. This method does not need to be synchronized, what matters is that each thread gets
- * a sequence of varying seeds.
- */
- protected int nextIterationSeed() {
- return iterationSeed = BitMixer.mixPhi(iterationSeed);
- }
-
- /** An iterator implementation for {@link #iterator}. */
- private final class EntryIterator extends AbstractIteratorslot
.
- */
- protected void shiftConflictingKeys(int gapSlot) {
- final char[] keys = this.keys;
- final double[] values = this.values;
- final int mask = this.mask;
-
- // Perform shifts of conflicting keys to fill in the gap.
- int distance = 0;
- while (true) {
- final int slot = (gapSlot + (++distance)) & mask;
- final char existing = keys[slot];
- if (((existing) == 0)) {
- break;
- }
-
- final int idealSlot = hashKey(existing);
- final int shift = (slot - idealSlot) & mask;
- if (shift >= distance) {
- // Entry at this position was originally at or before the gap slot.
- // Move the conflict-shifted entry to the gap's position and repeat the procedure
- // for any entries to the right of the current position, treating it
- // as the new gap.
- keys[gapSlot] = existing;
- values[gapSlot] = values[slot];
- gapSlot = slot;
- distance = 0;
- }
- }
-
- // Mark the last found gap slot without a conflict as empty.
- keys[gapSlot] = ((char) 0);
- values[gapSlot] = 0d;
- assigned--;
- }
-}
diff --git a/sources/main/java/com/carrotsearch/hppc/CharDoubleMap.java b/sources/main/java/com/carrotsearch/hppc/CharDoubleMap.java
deleted file mode 100644
index 2ba6e41b..00000000
--- a/sources/main/java/com/carrotsearch/hppc/CharDoubleMap.java
+++ /dev/null
@@ -1,205 +0,0 @@
-package com.carrotsearch.hppc;
-
-import com.carrotsearch.hppc.cursors.CharDoubleCursor;
-
-/** An associative container with unique binding from keys to a single value. */
-@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeVTypeMap.java")
-public interface CharDoubleMap extends CharDoubleAssociativeContainer {
- /**
- * @return Returns the value associated with the given key or the default value for the value
- * type, if the key is not associated with any value. For numeric value types, this default
- * value is 0, for object types it is {@code null}.
- */
- public double get(char key);
-
- /**
- * @return Returns the value associated with the given key or the provided default value if the
- * key is not associated with any value.
- */
- public double getOrDefault(char key, double defaultValue);
-
- /**
- * Place a given key and value in the container.
- *
- * @return The value previously stored under the given key in the map is returned.
- */
- public double put(char key, double value);
-
- /**
- * If the specified key is not already associated with a value, associates it with the given
- * value.
- *
- * @return {@code true} if {@code key} did not exist and {@code value} was placed in the map,
- * {@code false} otherwise.
- */
- public default boolean putIfAbsent(char key, double value) {
- int keyIndex = indexOf(key);
- if (indexExists(keyIndex)) {
- return false;
- } else {
- indexInsert(keyIndex, key, value);
- return true;
- }
- }
-
- /**
- * Puts all keys from another container to this map, replacing the values of existing keys, if
- * such keys are present.
- *
- * @return Returns the number of keys added to the map as a result of this call (not previously
- * present in the map). Values of existing keys are overwritten.
- */
- public int putAll(CharDoubleAssociativeContainer container);
-
- /**
- * Puts all keys from an iterable cursor to this map, replacing the values of existing keys, if
- * such keys are present.
- *
- * @return Returns the number of keys added to the map as a result of this call (not previously
- * present in the map). Values of existing keys are overwritten.
- */
- public int putAll(Iterable extends CharDoubleCursor> iterable);
-
- /**
- * If key
exists, putValue
is inserted into the map, otherwise any
- * existing value is incremented by additionValue
.
- *
- * @param key The key of the value to adjust.
- * @param putValue The value to put if key
does not exist.
- * @param incrementValue The value to add to the existing value if key
exists.
- * @return Returns the current value associated with key
(after changes).
- */
- public double putOrAdd(char key, double putValue, double incrementValue);
-
- /**
- * An equivalent of calling
- *
- *
- * putOrAdd(key, additionValue, additionValue);
- *
- *
- * @param key The key of the value to adjust.
- * @param additionValue The value to put or add to the existing value if key
exists.
- * @return Returns the current value associated with key
(after changes).
- */
- public double addTo(char key, double additionValue);
-
- /**
- * Remove all values at the given key. The default value for the key type is returned if the value
- * does not exist in the map.
- */
- public double remove(char key);
-
- /**
- * Compares the specified object with this set for equality. Returns {@code true} if and only if
- * the specified object is also a {@link CharDoubleMap} and both objects contains exactly the same
- * key-value pairs.
- */
- public boolean equals(Object obj);
-
- /**
- * @return A hash code of elements stored in the map. The hash code is defined as a sum of hash
- * codes of keys and values stored within the set). Because sum is commutative, this ensures
- * that different order of elements in a set does not affect the hash code.
- */
- public int hashCode();
-
- /**
- * Returns a logical "index" of a given key that can be used to speed up follow-up value setters
- * or getters in certain scenarios (conditional logic).
- *
- * true
if the index corresponds to an existing key or false
- * otherwise. This is equivalent to checking whether the index is a positive value (existing
- * keys) or a negative value (non-existing keys).
- */
- public boolean indexExists(int index);
-
- /**
- * Returns the value associated with an existing key.
- *
- * @see #indexOf
- * @param index The index of an existing key.
- * @return Returns the value currently associated with the key.
- * @throws AssertionError If assertions are enabled and the index does not correspond to an
- * existing key.
- */
- public double indexGet(int index);
-
- /**
- * Replaces the value associated with an existing key and returns any previous value stored for
- * that key.
- *
- * @see #indexOf
- * @param index The index of an existing key.
- * @return Returns the previous value associated with the key.
- * @throws AssertionError If assertions are enabled and the index does not correspond to an
- * existing key.
- */
- public double indexReplace(int index, double newValue);
-
- /**
- * Inserts a key-value pair for a key that is not present in the map. This method may help in
- * avoiding double recalculation of the key's hash.
- *
- * @see #indexOf
- * @param index The index of a previously non-existing key, as returned from {@link #indexOf}.
- * @throws AssertionError If assertions are enabled and the index corresponds to an existing key.
- */
- public void indexInsert(int index, char key, double value);
-
- /**
- * Removes a key-value pair at an index previously acquired from {@link #indexOf}.
- *
- * @see #indexOf
- * @param index The index of the key to remove, as returned from {@link #indexOf}.
- * @return Returns the previous value associated with the key.
- * @throws AssertionError If assertions are enabled and the index does not correspond to an
- * existing key.
- */
- public double indexRemove(int index);
-
- /**
- * Clear all keys and values in the container.
- *
- * @see #release()
- */
- public void clear();
-
- /**
- * Removes all elements from the collection and additionally releases any internal buffers.
- * Typically, if the object is to be reused, a simple {@link #clear()} should be a better
- * alternative since it'll avoid reallocation.
- *
- * @see #clear()
- */
- public void release();
-
- /**
- * Visually depict the distribution of keys.
- *
- * @param characters The number of characters to "squeeze" the entire buffer into.
- * @return Returns a sequence of characters where '.' depicts an empty fragment of the internal
- * buffer and 'X' depicts full or nearly full capacity within the buffer's range and anything
- * between 1 and 9 is between.
- */
- public String visualizeKeyDistribution(int characters);
-}
diff --git a/sources/main/java/com/carrotsearch/hppc/CharFloatAssociativeContainer.java b/sources/main/java/com/carrotsearch/hppc/CharFloatAssociativeContainer.java
deleted file mode 100644
index 10069a39..00000000
--- a/sources/main/java/com/carrotsearch/hppc/CharFloatAssociativeContainer.java
+++ /dev/null
@@ -1,105 +0,0 @@
-package com.carrotsearch.hppc;
-
-import com.carrotsearch.hppc.cursors.*;
-import com.carrotsearch.hppc.predicates.*;
-import com.carrotsearch.hppc.procedures.*;
-import java.util.Iterator;
-
-/**
- * An associative container from keys to (one or possibly more) values.
- *
- * @see CharContainer
- */
-@com.carrotsearch.hppc.Generated(
- date = "2024-06-04T15:20:17+0200",
- value = "KTypeVTypeAssociativeContainer.java")
-public interface CharFloatAssociativeContainer extends Iterable
- * for (IntShortCursor c : intShortMap) {
- * System.out.println("index=" + c.index + " key=" + c.key + " value=" + c.value);
- * }
- *
- * index
field inside the cursor gives the internal index inside the
- * container's implementation. The interpretation of this index depends on to the container.
- */
- @Override
- public Iteratortrue
if this container has an association to a value for the given key.
- */
- public boolean containsKey(char key);
-
- /**
- * @return Returns the current size (number of assigned keys) in the container.
- */
- public int size();
-
- /**
- * @return Return true
if this hash map contains no assigned keys.
- */
- public boolean isEmpty();
-
- /**
- * Removes all keys (and associated values) present in a given container. An alias to:
- *
- *
- * keys().removeAll(container)
- *
- *
- * but with no additional overhead.
- *
- * @return Returns the number of elements actually removed as a result of this call.
- */
- public int removeAll(CharContainer container);
-
- /**
- * Removes all keys (and associated values) for which the predicate returns true
.
- *
- * @return Returns the number of elements actually removed as a result of this call.
- */
- public int removeAll(CharPredicate predicate);
-
- /**
- * Removes all keys (and associated values) for which the predicate returns true
.
- *
- * @return Returns the number of elements actually removed as a result of this call.
- */
- public int removeAll(CharFloatPredicate predicate);
-
- /**
- * Applies a given procedure to all keys-value pairs in this container. Returns the argument (any
- * subclass of {@link CharFloatProcedure}. This lets the caller call methods of the argument by
- * chaining the call (even if the argument is an anonymous type) to retrieve computed values.
- */
- public true
.
- */
- public char
to float
, implemented using open addressing with
- * linear probing for collision resolution.
- *
- * @see HPPC interfaces diagram
- */
-@com.carrotsearch.hppc.Generated(
- date = "2024-06-04T15:20:16+0200",
- value = "KTypeVTypeHashMap.java")
-public class CharFloatHashMap implements CharFloatMap, Preallocable, Cloneable, Accountable {
-
- /** The array holding keys. */
- public char[] keys;
-
- /** The array holding values. */
- public float[] values;
-
- /**
- * The number of stored keys (assigned key slots), excluding the special "empty" key, if any (use
- * {@link #size()} instead).
- *
- * @see #size()
- */
- protected int assigned;
-
- /** Mask for slot scans in {@link #keys}. */
- protected int mask;
-
- /** Expand (rehash) {@link #keys} when {@link #assigned} hits this value. */
- protected int resizeAt;
-
- /** Special treatment for the "empty slot" key marker. */
- protected boolean hasEmptyKey;
-
- /** The load factor for {@link #keys}. */
- protected double loadFactor;
-
- /** Seed used to ensure the hash iteration order is different from an iteration to another. */
- protected int iterationSeed;
-
- /** New instance with sane defaults. */
- public CharFloatHashMap() {
- this(DEFAULT_EXPECTED_ELEMENTS);
- }
-
- /**
- * New instance with sane defaults.
- *
- * @param expectedElements The expected number of elements guaranteed not to cause buffer
- * expansion (inclusive).
- */
- public CharFloatHashMap(int expectedElements) {
- this(expectedElements, DEFAULT_LOAD_FACTOR);
- }
-
- /**
- * New instance with the provided defaults.
- *
- * @param expectedElements The expected number of elements guaranteed not to cause a rehash
- * (inclusive).
- * @param loadFactor The load factor for internal buffers. Insane load factors (zero, full
- * capacity) are rejected by {@link #verifyLoadFactor(double)}.
- */
- public CharFloatHashMap(int expectedElements, double loadFactor) {
- this.loadFactor = verifyLoadFactor(loadFactor);
- iterationSeed = HashContainers.nextIterationSeed();
- ensureCapacity(expectedElements);
- }
-
- /** Create a hash map from all key-value pairs of another container. */
- public CharFloatHashMap(CharFloatAssociativeContainer container) {
- this(container.size());
- putAll(container);
- }
-
- /** {@inheritDoc} */
- @Override
- public float put(char key, float value) {
- assert assigned < mask + 1;
-
- final int mask = this.mask;
- if (((key) == 0)) {
- float previousValue = hasEmptyKey ? values[mask + 1] : 0f;
- hasEmptyKey = true;
- values[mask + 1] = value;
- return previousValue;
- } else {
- final char[] keys = this.keys;
- int slot = hashKey(key) & mask;
-
- char existing;
- while (!((existing = keys[slot]) == 0)) {
- if (((key) == (existing))) {
- final float previousValue = values[slot];
- values[slot] = value;
- return previousValue;
- }
- slot = (slot + 1) & mask;
- }
-
- if (assigned == resizeAt) {
- allocateThenInsertThenRehash(slot, key, value);
- } else {
- keys[slot] = key;
- values[slot] = value;
- }
-
- assigned++;
- return 0f;
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public int putAll(CharFloatAssociativeContainer container) {
- final int count = size();
- for (CharFloatCursor c : container) {
- put(c.key, c.value);
- }
- return size() - count;
- }
-
- /** Puts all key/value pairs from a given iterable into this map. */
- @Override
- public int putAll(Iterable extends CharFloatCursor> iterable) {
- final int count = size();
- for (CharFloatCursor c : iterable) {
- put(c.key, c.value);
- }
- return size() - count;
- }
-
- /**
- * If key
exists, putValue
is inserted into the map, otherwise any
- * existing value is incremented by additionValue
.
- *
- * @param key The key of the value to adjust.
- * @param putValue The value to put if key
does not exist.
- * @param incrementValue The value to add to the existing value if key
exists.
- * @return Returns the current value associated with key
(after changes).
- */
- @Override
- public float putOrAdd(char key, float putValue, float incrementValue) {
- assert assigned < mask + 1;
-
- int keyIndex = indexOf(key);
- if (indexExists(keyIndex)) {
- putValue = ((float) ((values[keyIndex]) + (incrementValue)));
- indexReplace(keyIndex, putValue);
- } else {
- indexInsert(keyIndex, key, putValue);
- }
- return putValue;
- }
-
- /**
- * Adds incrementValue
to any existing value for the given key
or
- * inserts incrementValue
if key
did not previously exist.
- *
- * @param key The key of the value to adjust.
- * @param incrementValue The value to put or add to the existing value if key
exists.
- * @return Returns the current value associated with key
(after changes).
- */
- @Override
- public float addTo(char key, float incrementValue) {
- return putOrAdd(key, incrementValue, incrementValue);
- }
-
- /** {@inheritDoc} */
- @Override
- public float remove(char key) {
- final int mask = this.mask;
- if (((key) == 0)) {
- if (!hasEmptyKey) {
- return 0f;
- }
- hasEmptyKey = false;
- float previousValue = values[mask + 1];
- values[mask + 1] = 0f;
- return previousValue;
- } else {
- final char[] keys = this.keys;
- int slot = hashKey(key) & mask;
-
- char existing;
- while (!((existing = keys[slot]) == 0)) {
- if (((key) == (existing))) {
- final float previousValue = values[slot];
- shiftConflictingKeys(slot);
- return previousValue;
- }
- slot = (slot + 1) & mask;
- }
-
- return 0f;
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public int removeAll(CharContainer other) {
- final int before = size();
-
- // Try to iterate over the smaller set of values or
- // over the container that isn't implementing
- // efficient contains() lookup.
-
- if (other.size() >= size() && other instanceof CharLookupContainer) {
- if (hasEmptyKey && other.contains(((char) 0))) {
- hasEmptyKey = false;
- values[mask + 1] = 0f;
- }
-
- final char[] keys = this.keys;
- for (int slot = 0, max = this.mask; slot <= max; ) {
- char existing;
- if (!((existing = keys[slot]) == 0) && other.contains(existing)) {
- // Shift, do not increment slot.
- shiftConflictingKeys(slot);
- } else {
- slot++;
- }
- }
- } else {
- for (CharCursor c : other) {
- remove(c.value);
- }
- }
-
- return before - size();
- }
-
- /** {@inheritDoc} */
- @Override
- public int removeAll(CharFloatPredicate predicate) {
- final int before = size();
-
- final int mask = this.mask;
-
- if (hasEmptyKey) {
- if (predicate.apply(((char) 0), values[mask + 1])) {
- hasEmptyKey = false;
- values[mask + 1] = 0f;
- }
- }
-
- final char[] keys = this.keys;
- final float[] values = this.values;
- for (int slot = 0; slot <= mask; ) {
- char existing;
- if (!((existing = keys[slot]) == 0) && predicate.apply(existing, values[slot])) {
- // Shift, do not increment slot.
- shiftConflictingKeys(slot);
- } else {
- slot++;
- }
- }
-
- return before - size();
- }
-
- /** {@inheritDoc} */
- @Override
- public int removeAll(CharPredicate predicate) {
- final int before = size();
-
- if (hasEmptyKey) {
- if (predicate.apply(((char) 0))) {
- hasEmptyKey = false;
- values[mask + 1] = 0f;
- }
- }
-
- final char[] keys = this.keys;
- for (int slot = 0, max = this.mask; slot <= max; ) {
- char existing;
- if (!((existing = keys[slot]) == 0) && predicate.apply(existing)) {
- // Shift, do not increment slot.
- shiftConflictingKeys(slot);
- } else {
- slot++;
- }
- }
-
- return before - size();
- }
-
- /** {@inheritDoc} */
- @Override
- public float get(char key) {
- if (((key) == 0)) {
- return hasEmptyKey ? values[mask + 1] : 0f;
- } else {
- final char[] keys = this.keys;
- final int mask = this.mask;
- int slot = hashKey(key) & mask;
-
- char existing;
- while (!((existing = keys[slot]) == 0)) {
- if (((key) == (existing))) {
- return values[slot];
- }
- slot = (slot + 1) & mask;
- }
-
- return 0f;
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public float getOrDefault(char key, float defaultValue) {
- if (((key) == 0)) {
- return hasEmptyKey ? values[mask + 1] : defaultValue;
- } else {
- final char[] keys = this.keys;
- final int mask = this.mask;
- int slot = hashKey(key) & mask;
-
- char existing;
- while (!((existing = keys[slot]) == 0)) {
- if (((key) == (existing))) {
- return values[slot];
- }
- slot = (slot + 1) & mask;
- }
-
- return defaultValue;
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean containsKey(char key) {
- if (((key) == 0)) {
- return hasEmptyKey;
- } else {
- final char[] keys = this.keys;
- final int mask = this.mask;
- int slot = hashKey(key) & mask;
-
- char existing;
- while (!((existing = keys[slot]) == 0)) {
- if (((key) == (existing))) {
- return true;
- }
- slot = (slot + 1) & mask;
- }
-
- return false;
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public int indexOf(char key) {
- final int mask = this.mask;
- if (((key) == 0)) {
- return hasEmptyKey ? mask + 1 : ~(mask + 1);
- } else {
- final char[] keys = this.keys;
- int slot = hashKey(key) & mask;
-
- char existing;
- while (!((existing = keys[slot]) == 0)) {
- if (((key) == (existing))) {
- return slot;
- }
- slot = (slot + 1) & mask;
- }
-
- return ~slot;
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean indexExists(int index) {
- assert index < 0 || (index >= 0 && index <= mask) || (index == mask + 1 && hasEmptyKey);
-
- return index >= 0;
- }
-
- /** {@inheritDoc} */
- @Override
- public float indexGet(int index) {
- assert index >= 0 : "The index must point at an existing key.";
- assert index <= mask || (index == mask + 1 && hasEmptyKey);
-
- return values[index];
- }
-
- /** {@inheritDoc} */
- @Override
- public float indexReplace(int index, float newValue) {
- assert index >= 0 : "The index must point at an existing key.";
- assert index <= mask || (index == mask + 1 && hasEmptyKey);
-
- float previousValue = values[index];
- values[index] = newValue;
- return previousValue;
- }
-
- /** {@inheritDoc} */
- @Override
- public void indexInsert(int index, char key, float value) {
- assert index < 0 : "The index must not point at an existing key.";
-
- index = ~index;
- if (((key) == 0)) {
- assert index == mask + 1;
- values[index] = value;
- hasEmptyKey = true;
- } else {
- assert ((keys[index]) == 0);
-
- if (assigned == resizeAt) {
- allocateThenInsertThenRehash(index, key, value);
- } else {
- keys[index] = key;
- values[index] = value;
- }
-
- assigned++;
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public float indexRemove(int index) {
- assert index >= 0 : "The index must point at an existing key.";
- assert index <= mask || (index == mask + 1 && hasEmptyKey);
-
- float previousValue = values[index];
- if (index > mask) {
- assert index == mask + 1;
- hasEmptyKey = false;
- values[index] = 0f;
- } else {
- shiftConflictingKeys(index);
- }
- return previousValue;
- }
-
- /** {@inheritDoc} */
- @Override
- public void clear() {
- assigned = 0;
- hasEmptyKey = false;
-
- Arrays.fill(keys, ((char) 0));
- }
-
- /** {@inheritDoc} */
- @Override
- public void release() {
- assigned = 0;
- hasEmptyKey = false;
-
- keys = null;
- values = null;
- ensureCapacity(Containers.DEFAULT_EXPECTED_ELEMENTS);
- }
-
- /** {@inheritDoc} */
- @Override
- public int size() {
- return assigned + (hasEmptyKey ? 1 : 0);
- }
-
- /** {@inheritDoc} */
- public boolean isEmpty() {
- return size() == 0;
- }
-
- /** {@inheritDoc} */
- @Override
- public int hashCode() {
- int h = hasEmptyKey ? 0xDEADBEEF : 0;
- for (CharFloatCursor c : this) {
- h += BitMixer.mix(c.key) + BitMixer.mix(c.value);
- }
- return h;
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean equals(Object obj) {
- return (this == obj)
- || (obj != null && getClass() == obj.getClass() && equalElements(getClass().cast(obj)));
- }
-
- /** Return true if all keys of some other container exist in this container. */
- protected boolean equalElements(CharFloatHashMap other) {
- if (other.size() != size()) {
- return false;
- }
-
- for (CharFloatCursor c : other) {
- char key = c.key;
- if (!containsKey(key) || !(Float.floatToIntBits(c.value) == Float.floatToIntBits(get(key)))) {
- return false;
- }
- }
-
- return true;
- }
-
- /**
- * Ensure this container can hold at least the given number of keys (entries) without resizing its
- * buffers.
- *
- * @param expectedElements The total number of keys, inclusive.
- */
- @Override
- public void ensureCapacity(int expectedElements) {
- if (expectedElements > resizeAt || keys == null) {
- final char[] prevKeys = this.keys;
- final float[] prevValues = this.values;
- allocateBuffers(minBufferSize(expectedElements, loadFactor));
- if (prevKeys != null && !isEmpty()) {
- rehash(prevKeys, prevValues);
- }
- }
- }
-
- @Override
- public long ramBytesAllocated() {
- // int: iterationSeed, assigned, mask, resizeAt
- // double: loadFactor
- // boolean: hasEmptyKey
- return RamUsageEstimator.NUM_BYTES_OBJECT_HEADER
- + 4 * Integer.BYTES
- + Double.BYTES
- + 1
- + RamUsageEstimator.shallowSizeOfArray(keys)
- + RamUsageEstimator.shallowSizeOfArray(values);
- }
-
- @Override
- public long ramBytesUsed() {
- // int: iterationSeed, assigned, mask, resizeAt
- // double: loadFactor
- // boolean: hasEmptyKey
- return RamUsageEstimator.NUM_BYTES_OBJECT_HEADER
- + 4 * Integer.BYTES
- + Double.BYTES
- + 1
- + RamUsageEstimator.shallowUsedSizeOfArray(keys, size())
- + RamUsageEstimator.shallowUsedSizeOfArray(values, size());
- }
-
- /**
- * Provides the next iteration seed used to build the iteration starting slot and offset
- * increment. This method does not need to be synchronized, what matters is that each thread gets
- * a sequence of varying seeds.
- */
- protected int nextIterationSeed() {
- return iterationSeed = BitMixer.mixPhi(iterationSeed);
- }
-
- /** An iterator implementation for {@link #iterator}. */
- private final class EntryIterator extends AbstractIteratorslot
.
- */
- protected void shiftConflictingKeys(int gapSlot) {
- final char[] keys = this.keys;
- final float[] values = this.values;
- final int mask = this.mask;
-
- // Perform shifts of conflicting keys to fill in the gap.
- int distance = 0;
- while (true) {
- final int slot = (gapSlot + (++distance)) & mask;
- final char existing = keys[slot];
- if (((existing) == 0)) {
- break;
- }
-
- final int idealSlot = hashKey(existing);
- final int shift = (slot - idealSlot) & mask;
- if (shift >= distance) {
- // Entry at this position was originally at or before the gap slot.
- // Move the conflict-shifted entry to the gap's position and repeat the procedure
- // for any entries to the right of the current position, treating it
- // as the new gap.
- keys[gapSlot] = existing;
- values[gapSlot] = values[slot];
- gapSlot = slot;
- distance = 0;
- }
- }
-
- // Mark the last found gap slot without a conflict as empty.
- keys[gapSlot] = ((char) 0);
- values[gapSlot] = 0f;
- assigned--;
- }
-}
diff --git a/sources/main/java/com/carrotsearch/hppc/CharFloatMap.java b/sources/main/java/com/carrotsearch/hppc/CharFloatMap.java
deleted file mode 100644
index 4bf7569f..00000000
--- a/sources/main/java/com/carrotsearch/hppc/CharFloatMap.java
+++ /dev/null
@@ -1,205 +0,0 @@
-package com.carrotsearch.hppc;
-
-import com.carrotsearch.hppc.cursors.CharFloatCursor;
-
-/** An associative container with unique binding from keys to a single value. */
-@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeVTypeMap.java")
-public interface CharFloatMap extends CharFloatAssociativeContainer {
- /**
- * @return Returns the value associated with the given key or the default value for the value
- * type, if the key is not associated with any value. For numeric value types, this default
- * value is 0, for object types it is {@code null}.
- */
- public float get(char key);
-
- /**
- * @return Returns the value associated with the given key or the provided default value if the
- * key is not associated with any value.
- */
- public float getOrDefault(char key, float defaultValue);
-
- /**
- * Place a given key and value in the container.
- *
- * @return The value previously stored under the given key in the map is returned.
- */
- public float put(char key, float value);
-
- /**
- * If the specified key is not already associated with a value, associates it with the given
- * value.
- *
- * @return {@code true} if {@code key} did not exist and {@code value} was placed in the map,
- * {@code false} otherwise.
- */
- public default boolean putIfAbsent(char key, float value) {
- int keyIndex = indexOf(key);
- if (indexExists(keyIndex)) {
- return false;
- } else {
- indexInsert(keyIndex, key, value);
- return true;
- }
- }
-
- /**
- * Puts all keys from another container to this map, replacing the values of existing keys, if
- * such keys are present.
- *
- * @return Returns the number of keys added to the map as a result of this call (not previously
- * present in the map). Values of existing keys are overwritten.
- */
- public int putAll(CharFloatAssociativeContainer container);
-
- /**
- * Puts all keys from an iterable cursor to this map, replacing the values of existing keys, if
- * such keys are present.
- *
- * @return Returns the number of keys added to the map as a result of this call (not previously
- * present in the map). Values of existing keys are overwritten.
- */
- public int putAll(Iterable extends CharFloatCursor> iterable);
-
- /**
- * If key
exists, putValue
is inserted into the map, otherwise any
- * existing value is incremented by additionValue
.
- *
- * @param key The key of the value to adjust.
- * @param putValue The value to put if key
does not exist.
- * @param incrementValue The value to add to the existing value if key
exists.
- * @return Returns the current value associated with key
(after changes).
- */
- public float putOrAdd(char key, float putValue, float incrementValue);
-
- /**
- * An equivalent of calling
- *
- *
- * putOrAdd(key, additionValue, additionValue);
- *
- *
- * @param key The key of the value to adjust.
- * @param additionValue The value to put or add to the existing value if key
exists.
- * @return Returns the current value associated with key
(after changes).
- */
- public float addTo(char key, float additionValue);
-
- /**
- * Remove all values at the given key. The default value for the key type is returned if the value
- * does not exist in the map.
- */
- public float remove(char key);
-
- /**
- * Compares the specified object with this set for equality. Returns {@code true} if and only if
- * the specified object is also a {@link CharFloatMap} and both objects contains exactly the same
- * key-value pairs.
- */
- public boolean equals(Object obj);
-
- /**
- * @return A hash code of elements stored in the map. The hash code is defined as a sum of hash
- * codes of keys and values stored within the set). Because sum is commutative, this ensures
- * that different order of elements in a set does not affect the hash code.
- */
- public int hashCode();
-
- /**
- * Returns a logical "index" of a given key that can be used to speed up follow-up value setters
- * or getters in certain scenarios (conditional logic).
- *
- * true
if the index corresponds to an existing key or false
- * otherwise. This is equivalent to checking whether the index is a positive value (existing
- * keys) or a negative value (non-existing keys).
- */
- public boolean indexExists(int index);
-
- /**
- * Returns the value associated with an existing key.
- *
- * @see #indexOf
- * @param index The index of an existing key.
- * @return Returns the value currently associated with the key.
- * @throws AssertionError If assertions are enabled and the index does not correspond to an
- * existing key.
- */
- public float indexGet(int index);
-
- /**
- * Replaces the value associated with an existing key and returns any previous value stored for
- * that key.
- *
- * @see #indexOf
- * @param index The index of an existing key.
- * @return Returns the previous value associated with the key.
- * @throws AssertionError If assertions are enabled and the index does not correspond to an
- * existing key.
- */
- public float indexReplace(int index, float newValue);
-
- /**
- * Inserts a key-value pair for a key that is not present in the map. This method may help in
- * avoiding double recalculation of the key's hash.
- *
- * @see #indexOf
- * @param index The index of a previously non-existing key, as returned from {@link #indexOf}.
- * @throws AssertionError If assertions are enabled and the index corresponds to an existing key.
- */
- public void indexInsert(int index, char key, float value);
-
- /**
- * Removes a key-value pair at an index previously acquired from {@link #indexOf}.
- *
- * @see #indexOf
- * @param index The index of the key to remove, as returned from {@link #indexOf}.
- * @return Returns the previous value associated with the key.
- * @throws AssertionError If assertions are enabled and the index does not correspond to an
- * existing key.
- */
- public float indexRemove(int index);
-
- /**
- * Clear all keys and values in the container.
- *
- * @see #release()
- */
- public void clear();
-
- /**
- * Removes all elements from the collection and additionally releases any internal buffers.
- * Typically, if the object is to be reused, a simple {@link #clear()} should be a better
- * alternative since it'll avoid reallocation.
- *
- * @see #clear()
- */
- public void release();
-
- /**
- * Visually depict the distribution of keys.
- *
- * @param characters The number of characters to "squeeze" the entire buffer into.
- * @return Returns a sequence of characters where '.' depicts an empty fragment of the internal
- * buffer and 'X' depicts full or nearly full capacity within the buffer's range and anything
- * between 1 and 9 is between.
- */
- public String visualizeKeyDistribution(int characters);
-}
diff --git a/sources/main/java/com/carrotsearch/hppc/CharHashSet.java b/sources/main/java/com/carrotsearch/hppc/CharHashSet.java
deleted file mode 100644
index 58ad8f26..00000000
--- a/sources/main/java/com/carrotsearch/hppc/CharHashSet.java
+++ /dev/null
@@ -1,787 +0,0 @@
-package com.carrotsearch.hppc;
-
-import static com.carrotsearch.hppc.Containers.*;
-import static com.carrotsearch.hppc.HashContainers.*;
-
-import com.carrotsearch.hppc.cursors.*;
-import com.carrotsearch.hppc.predicates.*;
-import com.carrotsearch.hppc.procedures.*;
-import java.util.*;
-
-/**
- * A hash set of char
s, implemented using open addressing with linear probing for
- * collision resolution.
- *
- * @see HPPC interfaces diagram
- */
-@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:16+0200", value = "KTypeHashSet.java")
-public class CharHashSet extends AbstractCharCollection
- implements CharLookupContainer, CharSet, Preallocable, Cloneable, Accountable {
- /** The hash array holding keys. */
- public char[] keys;
-
- /**
- * The number of stored keys (assigned key slots), excluding the special "empty" key, if any.
- *
- * @see #size()
- * @see #hasEmptyKey
- */
- protected int assigned;
-
- /** Mask for slot scans in {@link #keys}. */
- protected int mask;
-
- /** Expand (rehash) {@link #keys} when {@link #assigned} hits this value. */
- protected int resizeAt;
-
- /** Special treatment for the "empty slot" key marker. */
- protected boolean hasEmptyKey;
-
- /** The load factor for {@link #keys}. */
- protected double loadFactor;
-
- /** Seed used to ensure the hash iteration order is different from an iteration to another. */
- protected int iterationSeed;
-
- /**
- * New instance with sane defaults.
- *
- * @see #CharHashSet(int, double)
- */
- public CharHashSet() {
- this(DEFAULT_EXPECTED_ELEMENTS, DEFAULT_LOAD_FACTOR);
- }
-
- /**
- * New instance with sane defaults.
- *
- * @see #CharHashSet(int, double)
- */
- public CharHashSet(int expectedElements) {
- this(expectedElements, DEFAULT_LOAD_FACTOR);
- }
-
- /**
- * New instance with the provided defaults.
- *
- * @param expectedElements The expected number of elements guaranteed not to cause a rehash
- * (inclusive).
- * @param loadFactor The load factor for internal buffers. Insane load factors (zero, full
- * capacity) are rejected by {@link #verifyLoadFactor(double)}.
- */
- public CharHashSet(int expectedElements, double loadFactor) {
- this.loadFactor = verifyLoadFactor(loadFactor);
- iterationSeed = HashContainers.nextIterationSeed();
- ensureCapacity(expectedElements);
- }
-
- /** New instance copying elements from another {@link CharContainer}. */
- public CharHashSet(CharContainer container) {
- this(container.size());
- addAll(container);
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean add(char key) {
- if (((key) == 0)) {
- assert ((keys[mask + 1]) == 0);
- boolean added = !hasEmptyKey;
- hasEmptyKey = true;
- return added;
- } else {
- final char[] keys = this.keys;
- final int mask = this.mask;
- int slot = hashKey(key) & mask;
-
- char existing;
- while (!((existing = keys[slot]) == 0)) {
- if (((key) == (existing))) {
- return false;
- }
- slot = (slot + 1) & mask;
- }
-
- if (assigned == resizeAt) {
- allocateThenInsertThenRehash(slot, key);
- } else {
- keys[slot] = key;
- }
-
- assigned++;
- return true;
- }
- }
-
- /**
- * Adds all elements from the given list (vararg) to this set.
- *
- * @return Returns the number of elements actually added as a result of this call (not previously
- * present in the set).
- */
- public final int addAll(char... elements) {
- ensureCapacity(elements.length);
- int count = 0;
- for (char e : elements) {
- if (add(e)) {
- count++;
- }
- }
- return count;
- }
-
- /**
- * Adds all elements from the given {@link CharContainer} to this set.
- *
- * @return Returns the number of elements actually added as a result of this call (not previously
- * present in the set).
- */
- public int addAll(CharContainer container) {
- ensureCapacity(container.size());
- return addAll((Iterable extends CharCursor>) container);
- }
-
- /**
- * Adds all elements from the given iterable to this set.
- *
- * @return Returns the number of elements actually added as a result of this call (not previously
- * present in the set).
- */
- public int addAll(Iterable extends CharCursor> iterable) {
- int count = 0;
- for (CharCursor cursor : iterable) {
- if (add(cursor.value)) {
- count++;
- }
- }
- return count;
- }
-
- /** {@inheritDoc} */
- @Override
- public char[] toArray() {
-
- final char[] cloned = (new char[size()]);
- int j = 0;
- if (hasEmptyKey) {
- cloned[j++] = ((char) 0);
- }
-
- final char[] keys = this.keys;
- int seed = nextIterationSeed();
- int inc = iterationIncrement(seed);
- for (int i = 0, mask = this.mask, slot = seed & mask;
- i <= mask;
- i++, slot = (slot + inc) & mask) {
- char existing;
- if (!((existing = keys[slot]) == 0)) {
- cloned[j++] = existing;
- }
- }
-
- return cloned;
- }
-
- /** An alias for the (preferred) {@link #removeAll}. */
- public boolean remove(char key) {
- if (((key) == 0)) {
- boolean hadEmptyKey = hasEmptyKey;
- hasEmptyKey = false;
- return hadEmptyKey;
- } else {
- final char[] keys = this.keys;
- final int mask = this.mask;
- int slot = hashKey(key) & mask;
-
- char existing;
- while (!((existing = keys[slot]) == 0)) {
- if (((key) == (existing))) {
- shiftConflictingKeys(slot);
- return true;
- }
- slot = (slot + 1) & mask;
- }
- return false;
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public int removeAll(char key) {
- return remove(key) ? 1 : 0;
- }
-
- /**
- * Removes all keys present in a given container.
- *
- * @return Returns the number of elements actually removed as a result of this call.
- */
- public int removeAll(CharContainer other) {
- final int before = size();
-
- // Try to iterate over the smaller set or over the container that isn't implementing
- // efficient contains() lookup.
-
- if (other.size() >= size() && other instanceof CharLookupContainer) {
- if (hasEmptyKey && other.contains(((char) 0))) {
- hasEmptyKey = false;
- }
-
- final char[] keys = this.keys;
- for (int slot = 0, max = this.mask; slot <= max; ) {
- char existing;
- if (!((existing = keys[slot]) == 0) && other.contains(existing)) {
- // Shift, do not increment slot.
- shiftConflictingKeys(slot);
- } else {
- slot++;
- }
- }
- } else {
- for (CharCursor c : other) {
- remove(c.value);
- }
- }
-
- return before - size();
- }
-
- /** {@inheritDoc} */
- @Override
- public int removeAll(CharPredicate predicate) {
- int before = size();
-
- if (hasEmptyKey) {
- if (predicate.apply(((char) 0))) {
- hasEmptyKey = false;
- }
- }
-
- final char[] keys = this.keys;
- for (int slot = 0, max = this.mask; slot <= max; ) {
- char existing;
- if (!((existing = keys[slot]) == 0)) {
- if (predicate.apply(existing)) {
- shiftConflictingKeys(slot);
- continue; // Repeat the check for the same slot i (shifted).
- }
- }
- slot++;
- }
-
- return before - size();
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean contains(char key) {
- if (((key) == 0)) {
- return hasEmptyKey;
- } else {
- final char[] keys = this.keys;
- final int mask = this.mask;
- int slot = hashKey(key) & mask;
- char existing;
- while (!((existing = keys[slot]) == 0)) {
- if (((key) == (existing))) {
- return true;
- }
- slot = (slot + 1) & mask;
- }
- return false;
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public void clear() {
- assigned = 0;
- hasEmptyKey = false;
- Arrays.fill(keys, ((char) 0));
- }
-
- /** {@inheritDoc} */
- @Override
- public void release() {
- assigned = 0;
- hasEmptyKey = false;
- keys = null;
- ensureCapacity(Containers.DEFAULT_EXPECTED_ELEMENTS);
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean isEmpty() {
- return size() == 0;
- }
-
- /**
- * Ensure this container can hold at least the given number of elements without resizing its
- * buffers.
- *
- * @param expectedElements The total number of elements, inclusive.
- */
- @Override
- public void ensureCapacity(int expectedElements) {
- if (expectedElements > resizeAt || keys == null) {
- final char[] prevKeys = this.keys;
- allocateBuffers(minBufferSize(expectedElements, loadFactor));
- if (prevKeys != null && !isEmpty()) {
- rehash(prevKeys);
- }
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public int size() {
- return assigned + (hasEmptyKey ? 1 : 0);
- }
-
- /** {@inheritDoc} */
- @Override
- public int hashCode() {
- int h = hasEmptyKey ? 0xDEADBEEF : 0;
- final char[] keys = this.keys;
- for (int slot = mask; slot >= 0; slot--) {
- char existing;
- if (!((existing = keys[slot]) == 0)) {
- h += BitMixer.mix(existing);
- }
- }
- return h;
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean equals(Object obj) {
- return (this == obj)
- || (obj != null && getClass() == obj.getClass() && sameKeys(getClass().cast(obj)));
- }
-
- /** Return true if all keys of some other container exist in this container. */
- private boolean sameKeys(CharSet other) {
- if (other.size() != size()) {
- return false;
- }
-
- for (CharCursor c : other) {
- if (!contains(c.value)) {
- return false;
- }
- }
-
- return true;
- }
-
- /** {@inheritDoc} */
- @Override
- public CharHashSet clone() {
- try {
-
- CharHashSet cloned = (CharHashSet) super.clone();
- cloned.keys = keys.clone();
- cloned.hasEmptyKey = hasEmptyKey;
- cloned.iterationSeed = HashContainers.nextIterationSeed();
- return cloned;
- } catch (CloneNotSupportedException e) {
- throw new RuntimeException(e);
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public Iteratorchar
. The elements
- * are copied from the argument to the internal buffer.
- */
- public static CharHashSet from(char... elements) {
- final CharHashSet set = new CharHashSet(elements.length);
- set.addAll(elements);
- return set;
- }
-
- /**
- * Returns a hash code for the given key.
- *
- * true
if the index corresponds to an existing key or false
- * otherwise. This is equivalent to checking whether the index is a positive value (existing
- * keys) or a negative value (non-existing keys).
- */
- public boolean indexExists(int index) {
- assert index < 0 || index <= mask || (index == mask + 1 && hasEmptyKey);
-
- return index >= 0;
- }
-
- /**
- * Returns the exact value of the existing key. This method makes sense for sets of objects which
- * define custom key-equality relationship.
- *
- * @see #indexOf
- * @param index The index of an existing key.
- * @return Returns the equivalent key currently stored in the set.
- * @throws AssertionError If assertions are enabled and the index does not correspond to an
- * existing key.
- */
- public char indexGet(int index) {
- assert index >= 0 : "The index must point at an existing key.";
- assert index <= mask || (index == mask + 1 && hasEmptyKey);
-
- return keys[index];
- }
-
- /**
- * Replaces the existing equivalent key with the given one and returns any previous value stored
- * for that key.
- *
- * @see #indexOf
- * @param index The index of an existing key.
- * @param equivalentKey The key to put in the set as a replacement. Must be equivalent to the key
- * currently stored at the provided index.
- * @return Returns the previous key stored in the set.
- * @throws AssertionError If assertions are enabled and the index does not correspond to an
- * existing key.
- */
- public char indexReplace(int index, char equivalentKey) {
- assert index >= 0 : "The index must point at an existing key.";
- assert index <= mask || (index == mask + 1 && hasEmptyKey);
- assert ((keys[index]) == (equivalentKey));
-
- char previousValue = keys[index];
- keys[index] = equivalentKey;
- return previousValue;
- }
-
- /**
- * Inserts a key for an index that is not present in the set. This method may help in avoiding
- * double recalculation of the key's hash.
- *
- * @see #indexOf
- * @param index The index of a previously non-existing key, as returned from {@link #indexOf}.
- * @throws AssertionError If assertions are enabled and the index does not correspond to an
- * existing key.
- */
- public void indexInsert(int index, char key) {
- assert index < 0 : "The index must not point at an existing key.";
-
- index = ~index;
- if (((key) == 0)) {
- assert index == mask + 1;
- assert ((keys[index]) == 0);
- hasEmptyKey = true;
- } else {
- assert ((keys[index]) == 0);
-
- if (assigned == resizeAt) {
- allocateThenInsertThenRehash(index, key);
- } else {
- keys[index] = key;
- }
-
- assigned++;
- }
- }
-
- /**
- * Removes a key at an index previously acquired from {@link #indexOf}.
- *
- * @see #indexOf
- * @param index The index of the key to remove, as returned from {@link #indexOf}.
- * @throws AssertionError If assertions are enabled and the index does not correspond to an
- * existing key.
- */
- public void indexRemove(int index) {
- assert index >= 0 : "The index must point at an existing key.";
- assert index <= mask || (index == mask + 1 && hasEmptyKey);
-
- if (index > mask) {
- hasEmptyKey = false;
- } else {
- shiftConflictingKeys(index);
- }
- }
-
- @Override
- public String visualizeKeyDistribution(int characters) {
- return CharBufferVisualizer.visualizeKeyDistribution(keys, mask, characters);
- }
-
- /**
- * Validate load factor range and return it. Override and suppress if you need insane load
- * factors.
- */
- protected double verifyLoadFactor(double loadFactor) {
- checkLoadFactor(loadFactor, MIN_LOAD_FACTOR, MAX_LOAD_FACTOR);
- return loadFactor;
- }
-
- /** Rehash from old buffers to new buffers. */
- protected void rehash(char[] fromKeys) {
- assert HashContainers.checkPowerOfTwo(fromKeys.length - 1);
-
- // Rehash all stored keys into the new buffers.
- final char[] keys = this.keys;
- final int mask = this.mask;
- char existing;
- for (int i = fromKeys.length - 1; --i >= 0; ) {
- if (!((existing = fromKeys[i]) == 0)) {
- int slot = hashKey(existing) & mask;
- while (!((keys[slot]) == 0)) {
- slot = (slot + 1) & mask;
- }
- keys[slot] = existing;
- }
- }
- }
-
- /**
- * Allocate new internal buffers. This method attempts to allocate and assign internal buffers
- * atomically (either allocations succeed or not).
- */
- protected void allocateBuffers(int arraySize) {
- assert Integer.bitCount(arraySize) == 1;
-
- // Ensure no change is done if we hit an OOM.
- char[] prevKeys = this.keys;
- try {
- int emptyElementSlot = 1;
- this.keys = (new char[arraySize + emptyElementSlot]);
- } catch (OutOfMemoryError e) {
- this.keys = prevKeys;
- throw new BufferAllocationException(
- "Not enough memory to allocate buffers for rehashing: %,d -> %,d",
- e, this.keys == null ? 0 : size(), arraySize);
- }
-
- this.resizeAt = expandAtCount(arraySize, loadFactor);
- this.mask = arraySize - 1;
- }
-
- /**
- * This method is invoked when there is a new key to be inserted into the buffer but there is not
- * enough empty slots to do so.
- *
- * slot
. */
- protected void shiftConflictingKeys(int gapSlot) {
- final char[] keys = this.keys;
- final int mask = this.mask;
-
- // Perform shifts of conflicting keys to fill in the gap.
- int distance = 0;
- while (true) {
- final int slot = (gapSlot + (++distance)) & mask;
- final char existing = keys[slot];
- if (((existing) == 0)) {
- break;
- }
-
- final int idealSlot = hashKey(existing);
- final int shift = (slot - idealSlot) & mask;
- if (shift >= distance) {
- // Entry at this position was originally at or before the gap slot.
- // Move the conflict-shifted entry to the gap's position and repeat the procedure
- // for any entries to the right of the current position, treating it
- // as the new gap.
- keys[gapSlot] = existing;
- gapSlot = slot;
- distance = 0;
- }
- }
-
- // Mark the last found gap slot without a conflict as empty.
- keys[gapSlot] = ((char) 0);
- assigned--;
- }
-}
diff --git a/sources/main/java/com/carrotsearch/hppc/CharIndexedContainer.java b/sources/main/java/com/carrotsearch/hppc/CharIndexedContainer.java
deleted file mode 100644
index 96824521..00000000
--- a/sources/main/java/com/carrotsearch/hppc/CharIndexedContainer.java
+++ /dev/null
@@ -1,91 +0,0 @@
-package com.carrotsearch.hppc;
-
-import java.util.RandomAccess;
-
-/**
- * An indexed container provides random access to elements based on an index
. Indexes
- * are zero-based.
- */
-@com.carrotsearch.hppc.Generated(
- date = "2024-06-04T15:20:17+0200",
- value = "KTypeIndexedContainer.java")
-public interface CharIndexedContainer extends CharCollection, RandomAccess {
- /**
- * Removes the first element that equals e1
, returning whether an element has been
- * removed.
- */
- public boolean removeElement(char e1);
-
- /**
- * Removes the first element that equals e1
, returning its deleted position or
- * -1
if the element was not found.
- */
- public int removeFirst(char e1);
-
- /**
- * Removes the last element that equals e1
, returning its deleted position or
- * -1
if the element was not found.
- */
- public int removeLast(char e1);
-
- /**
- * Returns the index of the first occurrence of the specified element in this list, or -1 if this
- * list does not contain the element.
- */
- public int indexOf(char e1);
-
- /**
- * Returns the index of the last occurrence of the specified element in this list, or -1 if this
- * list does not contain the element.
- */
- public int lastIndexOf(char e1);
-
- /** Adds an element to the end of this container (the last index is incremented by one). */
- public void add(char e1);
-
- /**
- * Inserts the specified element at the specified position in this list.
- *
- * @param index The index at which the element should be inserted, shifting any existing and
- * subsequent elements to the right.
- */
- public void insert(int index, char e1);
-
- /**
- * Replaces the element at the specified position in this list with the specified element.
- *
- * @return Returns the previous value in the list.
- */
- public char set(int index, char e1);
-
- /**
- * @return Returns the element at index index
from the list.
- */
- public char get(int index);
-
- /**
- * Removes the element at the specified position in this container and returns it.
- *
- * @see #removeFirst
- * @see #removeLast
- * @see #removeAll
- */
- public char removeAt(int index);
-
- /** Removes and returns the last element of this container. This container must not be empty. */
- public char removeLast();
-
- /**
- * Removes from this container all of the elements with indexes between fromIndex
,
- * inclusive, and toIndex
, exclusive.
- */
- public void removeRange(int fromIndex, int toIndex);
-
- /** Returns this container elements as a stream. */
-
- /** Sorts the elements in this container and returns this container. */
- public CharIndexedContainer sort();
-
- /** Reverses the elements in this container and returns this container. */
- public CharIndexedContainer reverse();
-}
diff --git a/sources/main/java/com/carrotsearch/hppc/CharIntAssociativeContainer.java b/sources/main/java/com/carrotsearch/hppc/CharIntAssociativeContainer.java
deleted file mode 100644
index 08c5d64a..00000000
--- a/sources/main/java/com/carrotsearch/hppc/CharIntAssociativeContainer.java
+++ /dev/null
@@ -1,105 +0,0 @@
-package com.carrotsearch.hppc;
-
-import com.carrotsearch.hppc.cursors.*;
-import com.carrotsearch.hppc.predicates.*;
-import com.carrotsearch.hppc.procedures.*;
-import java.util.Iterator;
-
-/**
- * An associative container from keys to (one or possibly more) values.
- *
- * @see CharContainer
- */
-@com.carrotsearch.hppc.Generated(
- date = "2024-06-04T15:20:17+0200",
- value = "KTypeVTypeAssociativeContainer.java")
-public interface CharIntAssociativeContainer extends Iterable
- * for (IntShortCursor c : intShortMap) {
- * System.out.println("index=" + c.index + " key=" + c.key + " value=" + c.value);
- * }
- *
- * index
field inside the cursor gives the internal index inside the
- * container's implementation. The interpretation of this index depends on to the container.
- */
- @Override
- public Iteratortrue
if this container has an association to a value for the given key.
- */
- public boolean containsKey(char key);
-
- /**
- * @return Returns the current size (number of assigned keys) in the container.
- */
- public int size();
-
- /**
- * @return Return true
if this hash map contains no assigned keys.
- */
- public boolean isEmpty();
-
- /**
- * Removes all keys (and associated values) present in a given container. An alias to:
- *
- *
- * keys().removeAll(container)
- *
- *
- * but with no additional overhead.
- *
- * @return Returns the number of elements actually removed as a result of this call.
- */
- public int removeAll(CharContainer container);
-
- /**
- * Removes all keys (and associated values) for which the predicate returns true
.
- *
- * @return Returns the number of elements actually removed as a result of this call.
- */
- public int removeAll(CharPredicate predicate);
-
- /**
- * Removes all keys (and associated values) for which the predicate returns true
.
- *
- * @return Returns the number of elements actually removed as a result of this call.
- */
- public int removeAll(CharIntPredicate predicate);
-
- /**
- * Applies a given procedure to all keys-value pairs in this container. Returns the argument (any
- * subclass of {@link CharIntProcedure}. This lets the caller call methods of the argument by
- * chaining the call (even if the argument is an anonymous type) to retrieve computed values.
- */
- public true
.
- */
- public char
to int
, implemented using open addressing with
- * linear probing for collision resolution.
- *
- * @see HPPC interfaces diagram
- */
-@com.carrotsearch.hppc.Generated(
- date = "2024-06-04T15:20:16+0200",
- value = "KTypeVTypeHashMap.java")
-public class CharIntHashMap implements CharIntMap, Preallocable, Cloneable, Accountable {
-
- /** The array holding keys. */
- public char[] keys;
-
- /** The array holding values. */
- public int[] values;
-
- /**
- * The number of stored keys (assigned key slots), excluding the special "empty" key, if any (use
- * {@link #size()} instead).
- *
- * @see #size()
- */
- protected int assigned;
-
- /** Mask for slot scans in {@link #keys}. */
- protected int mask;
-
- /** Expand (rehash) {@link #keys} when {@link #assigned} hits this value. */
- protected int resizeAt;
-
- /** Special treatment for the "empty slot" key marker. */
- protected boolean hasEmptyKey;
-
- /** The load factor for {@link #keys}. */
- protected double loadFactor;
-
- /** Seed used to ensure the hash iteration order is different from an iteration to another. */
- protected int iterationSeed;
-
- /** New instance with sane defaults. */
- public CharIntHashMap() {
- this(DEFAULT_EXPECTED_ELEMENTS);
- }
-
- /**
- * New instance with sane defaults.
- *
- * @param expectedElements The expected number of elements guaranteed not to cause buffer
- * expansion (inclusive).
- */
- public CharIntHashMap(int expectedElements) {
- this(expectedElements, DEFAULT_LOAD_FACTOR);
- }
-
- /**
- * New instance with the provided defaults.
- *
- * @param expectedElements The expected number of elements guaranteed not to cause a rehash
- * (inclusive).
- * @param loadFactor The load factor for internal buffers. Insane load factors (zero, full
- * capacity) are rejected by {@link #verifyLoadFactor(double)}.
- */
- public CharIntHashMap(int expectedElements, double loadFactor) {
- this.loadFactor = verifyLoadFactor(loadFactor);
- iterationSeed = HashContainers.nextIterationSeed();
- ensureCapacity(expectedElements);
- }
-
- /** Create a hash map from all key-value pairs of another container. */
- public CharIntHashMap(CharIntAssociativeContainer container) {
- this(container.size());
- putAll(container);
- }
-
- /** {@inheritDoc} */
- @Override
- public int put(char key, int value) {
- assert assigned < mask + 1;
-
- final int mask = this.mask;
- if (((key) == 0)) {
- int previousValue = hasEmptyKey ? values[mask + 1] : 0;
- hasEmptyKey = true;
- values[mask + 1] = value;
- return previousValue;
- } else {
- final char[] keys = this.keys;
- int slot = hashKey(key) & mask;
-
- char existing;
- while (!((existing = keys[slot]) == 0)) {
- if (((key) == (existing))) {
- final int previousValue = values[slot];
- values[slot] = value;
- return previousValue;
- }
- slot = (slot + 1) & mask;
- }
-
- if (assigned == resizeAt) {
- allocateThenInsertThenRehash(slot, key, value);
- } else {
- keys[slot] = key;
- values[slot] = value;
- }
-
- assigned++;
- return 0;
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public int putAll(CharIntAssociativeContainer container) {
- final int count = size();
- for (CharIntCursor c : container) {
- put(c.key, c.value);
- }
- return size() - count;
- }
-
- /** Puts all key/value pairs from a given iterable into this map. */
- @Override
- public int putAll(Iterable extends CharIntCursor> iterable) {
- final int count = size();
- for (CharIntCursor c : iterable) {
- put(c.key, c.value);
- }
- return size() - count;
- }
-
- /**
- * If key
exists, putValue
is inserted into the map, otherwise any
- * existing value is incremented by additionValue
.
- *
- * @param key The key of the value to adjust.
- * @param putValue The value to put if key
does not exist.
- * @param incrementValue The value to add to the existing value if key
exists.
- * @return Returns the current value associated with key
(after changes).
- */
- @Override
- public int putOrAdd(char key, int putValue, int incrementValue) {
- assert assigned < mask + 1;
-
- int keyIndex = indexOf(key);
- if (indexExists(keyIndex)) {
- putValue = ((int) ((values[keyIndex]) + (incrementValue)));
- indexReplace(keyIndex, putValue);
- } else {
- indexInsert(keyIndex, key, putValue);
- }
- return putValue;
- }
-
- /**
- * Adds incrementValue
to any existing value for the given key
or
- * inserts incrementValue
if key
did not previously exist.
- *
- * @param key The key of the value to adjust.
- * @param incrementValue The value to put or add to the existing value if key
exists.
- * @return Returns the current value associated with key
(after changes).
- */
- @Override
- public int addTo(char key, int incrementValue) {
- return putOrAdd(key, incrementValue, incrementValue);
- }
-
- /** {@inheritDoc} */
- @Override
- public int remove(char key) {
- final int mask = this.mask;
- if (((key) == 0)) {
- if (!hasEmptyKey) {
- return 0;
- }
- hasEmptyKey = false;
- int previousValue = values[mask + 1];
- values[mask + 1] = 0;
- return previousValue;
- } else {
- final char[] keys = this.keys;
- int slot = hashKey(key) & mask;
-
- char existing;
- while (!((existing = keys[slot]) == 0)) {
- if (((key) == (existing))) {
- final int previousValue = values[slot];
- shiftConflictingKeys(slot);
- return previousValue;
- }
- slot = (slot + 1) & mask;
- }
-
- return 0;
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public int removeAll(CharContainer other) {
- final int before = size();
-
- // Try to iterate over the smaller set of values or
- // over the container that isn't implementing
- // efficient contains() lookup.
-
- if (other.size() >= size() && other instanceof CharLookupContainer) {
- if (hasEmptyKey && other.contains(((char) 0))) {
- hasEmptyKey = false;
- values[mask + 1] = 0;
- }
-
- final char[] keys = this.keys;
- for (int slot = 0, max = this.mask; slot <= max; ) {
- char existing;
- if (!((existing = keys[slot]) == 0) && other.contains(existing)) {
- // Shift, do not increment slot.
- shiftConflictingKeys(slot);
- } else {
- slot++;
- }
- }
- } else {
- for (CharCursor c : other) {
- remove(c.value);
- }
- }
-
- return before - size();
- }
-
- /** {@inheritDoc} */
- @Override
- public int removeAll(CharIntPredicate predicate) {
- final int before = size();
-
- final int mask = this.mask;
-
- if (hasEmptyKey) {
- if (predicate.apply(((char) 0), values[mask + 1])) {
- hasEmptyKey = false;
- values[mask + 1] = 0;
- }
- }
-
- final char[] keys = this.keys;
- final int[] values = this.values;
- for (int slot = 0; slot <= mask; ) {
- char existing;
- if (!((existing = keys[slot]) == 0) && predicate.apply(existing, values[slot])) {
- // Shift, do not increment slot.
- shiftConflictingKeys(slot);
- } else {
- slot++;
- }
- }
-
- return before - size();
- }
-
- /** {@inheritDoc} */
- @Override
- public int removeAll(CharPredicate predicate) {
- final int before = size();
-
- if (hasEmptyKey) {
- if (predicate.apply(((char) 0))) {
- hasEmptyKey = false;
- values[mask + 1] = 0;
- }
- }
-
- final char[] keys = this.keys;
- for (int slot = 0, max = this.mask; slot <= max; ) {
- char existing;
- if (!((existing = keys[slot]) == 0) && predicate.apply(existing)) {
- // Shift, do not increment slot.
- shiftConflictingKeys(slot);
- } else {
- slot++;
- }
- }
-
- return before - size();
- }
-
- /** {@inheritDoc} */
- @Override
- public int get(char key) {
- if (((key) == 0)) {
- return hasEmptyKey ? values[mask + 1] : 0;
- } else {
- final char[] keys = this.keys;
- final int mask = this.mask;
- int slot = hashKey(key) & mask;
-
- char existing;
- while (!((existing = keys[slot]) == 0)) {
- if (((key) == (existing))) {
- return values[slot];
- }
- slot = (slot + 1) & mask;
- }
-
- return 0;
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public int getOrDefault(char key, int defaultValue) {
- if (((key) == 0)) {
- return hasEmptyKey ? values[mask + 1] : defaultValue;
- } else {
- final char[] keys = this.keys;
- final int mask = this.mask;
- int slot = hashKey(key) & mask;
-
- char existing;
- while (!((existing = keys[slot]) == 0)) {
- if (((key) == (existing))) {
- return values[slot];
- }
- slot = (slot + 1) & mask;
- }
-
- return defaultValue;
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean containsKey(char key) {
- if (((key) == 0)) {
- return hasEmptyKey;
- } else {
- final char[] keys = this.keys;
- final int mask = this.mask;
- int slot = hashKey(key) & mask;
-
- char existing;
- while (!((existing = keys[slot]) == 0)) {
- if (((key) == (existing))) {
- return true;
- }
- slot = (slot + 1) & mask;
- }
-
- return false;
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public int indexOf(char key) {
- final int mask = this.mask;
- if (((key) == 0)) {
- return hasEmptyKey ? mask + 1 : ~(mask + 1);
- } else {
- final char[] keys = this.keys;
- int slot = hashKey(key) & mask;
-
- char existing;
- while (!((existing = keys[slot]) == 0)) {
- if (((key) == (existing))) {
- return slot;
- }
- slot = (slot + 1) & mask;
- }
-
- return ~slot;
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean indexExists(int index) {
- assert index < 0 || (index >= 0 && index <= mask) || (index == mask + 1 && hasEmptyKey);
-
- return index >= 0;
- }
-
- /** {@inheritDoc} */
- @Override
- public int indexGet(int index) {
- assert index >= 0 : "The index must point at an existing key.";
- assert index <= mask || (index == mask + 1 && hasEmptyKey);
-
- return values[index];
- }
-
- /** {@inheritDoc} */
- @Override
- public int indexReplace(int index, int newValue) {
- assert index >= 0 : "The index must point at an existing key.";
- assert index <= mask || (index == mask + 1 && hasEmptyKey);
-
- int previousValue = values[index];
- values[index] = newValue;
- return previousValue;
- }
-
- /** {@inheritDoc} */
- @Override
- public void indexInsert(int index, char key, int value) {
- assert index < 0 : "The index must not point at an existing key.";
-
- index = ~index;
- if (((key) == 0)) {
- assert index == mask + 1;
- values[index] = value;
- hasEmptyKey = true;
- } else {
- assert ((keys[index]) == 0);
-
- if (assigned == resizeAt) {
- allocateThenInsertThenRehash(index, key, value);
- } else {
- keys[index] = key;
- values[index] = value;
- }
-
- assigned++;
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public int indexRemove(int index) {
- assert index >= 0 : "The index must point at an existing key.";
- assert index <= mask || (index == mask + 1 && hasEmptyKey);
-
- int previousValue = values[index];
- if (index > mask) {
- assert index == mask + 1;
- hasEmptyKey = false;
- values[index] = 0;
- } else {
- shiftConflictingKeys(index);
- }
- return previousValue;
- }
-
- /** {@inheritDoc} */
- @Override
- public void clear() {
- assigned = 0;
- hasEmptyKey = false;
-
- Arrays.fill(keys, ((char) 0));
- }
-
- /** {@inheritDoc} */
- @Override
- public void release() {
- assigned = 0;
- hasEmptyKey = false;
-
- keys = null;
- values = null;
- ensureCapacity(Containers.DEFAULT_EXPECTED_ELEMENTS);
- }
-
- /** {@inheritDoc} */
- @Override
- public int size() {
- return assigned + (hasEmptyKey ? 1 : 0);
- }
-
- /** {@inheritDoc} */
- public boolean isEmpty() {
- return size() == 0;
- }
-
- /** {@inheritDoc} */
- @Override
- public int hashCode() {
- int h = hasEmptyKey ? 0xDEADBEEF : 0;
- for (CharIntCursor c : this) {
- h += BitMixer.mix(c.key) + BitMixer.mix(c.value);
- }
- return h;
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean equals(Object obj) {
- return (this == obj)
- || (obj != null && getClass() == obj.getClass() && equalElements(getClass().cast(obj)));
- }
-
- /** Return true if all keys of some other container exist in this container. */
- protected boolean equalElements(CharIntHashMap other) {
- if (other.size() != size()) {
- return false;
- }
-
- for (CharIntCursor c : other) {
- char key = c.key;
- if (!containsKey(key) || !((c.value) == (get(key)))) {
- return false;
- }
- }
-
- return true;
- }
-
- /**
- * Ensure this container can hold at least the given number of keys (entries) without resizing its
- * buffers.
- *
- * @param expectedElements The total number of keys, inclusive.
- */
- @Override
- public void ensureCapacity(int expectedElements) {
- if (expectedElements > resizeAt || keys == null) {
- final char[] prevKeys = this.keys;
- final int[] prevValues = this.values;
- allocateBuffers(minBufferSize(expectedElements, loadFactor));
- if (prevKeys != null && !isEmpty()) {
- rehash(prevKeys, prevValues);
- }
- }
- }
-
- @Override
- public long ramBytesAllocated() {
- // int: iterationSeed, assigned, mask, resizeAt
- // double: loadFactor
- // boolean: hasEmptyKey
- return RamUsageEstimator.NUM_BYTES_OBJECT_HEADER
- + 4 * Integer.BYTES
- + Double.BYTES
- + 1
- + RamUsageEstimator.shallowSizeOfArray(keys)
- + RamUsageEstimator.shallowSizeOfArray(values);
- }
-
- @Override
- public long ramBytesUsed() {
- // int: iterationSeed, assigned, mask, resizeAt
- // double: loadFactor
- // boolean: hasEmptyKey
- return RamUsageEstimator.NUM_BYTES_OBJECT_HEADER
- + 4 * Integer.BYTES
- + Double.BYTES
- + 1
- + RamUsageEstimator.shallowUsedSizeOfArray(keys, size())
- + RamUsageEstimator.shallowUsedSizeOfArray(values, size());
- }
-
- /**
- * Provides the next iteration seed used to build the iteration starting slot and offset
- * increment. This method does not need to be synchronized, what matters is that each thread gets
- * a sequence of varying seeds.
- */
- protected int nextIterationSeed() {
- return iterationSeed = BitMixer.mixPhi(iterationSeed);
- }
-
- /** An iterator implementation for {@link #iterator}. */
- private final class EntryIterator extends AbstractIteratorslot
.
- */
- protected void shiftConflictingKeys(int gapSlot) {
- final char[] keys = this.keys;
- final int[] values = this.values;
- final int mask = this.mask;
-
- // Perform shifts of conflicting keys to fill in the gap.
- int distance = 0;
- while (true) {
- final int slot = (gapSlot + (++distance)) & mask;
- final char existing = keys[slot];
- if (((existing) == 0)) {
- break;
- }
-
- final int idealSlot = hashKey(existing);
- final int shift = (slot - idealSlot) & mask;
- if (shift >= distance) {
- // Entry at this position was originally at or before the gap slot.
- // Move the conflict-shifted entry to the gap's position and repeat the procedure
- // for any entries to the right of the current position, treating it
- // as the new gap.
- keys[gapSlot] = existing;
- values[gapSlot] = values[slot];
- gapSlot = slot;
- distance = 0;
- }
- }
-
- // Mark the last found gap slot without a conflict as empty.
- keys[gapSlot] = ((char) 0);
- values[gapSlot] = 0;
- assigned--;
- }
-}
diff --git a/sources/main/java/com/carrotsearch/hppc/CharIntMap.java b/sources/main/java/com/carrotsearch/hppc/CharIntMap.java
deleted file mode 100644
index 8c2f24e0..00000000
--- a/sources/main/java/com/carrotsearch/hppc/CharIntMap.java
+++ /dev/null
@@ -1,205 +0,0 @@
-package com.carrotsearch.hppc;
-
-import com.carrotsearch.hppc.cursors.CharIntCursor;
-
-/** An associative container with unique binding from keys to a single value. */
-@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeVTypeMap.java")
-public interface CharIntMap extends CharIntAssociativeContainer {
- /**
- * @return Returns the value associated with the given key or the default value for the value
- * type, if the key is not associated with any value. For numeric value types, this default
- * value is 0, for object types it is {@code null}.
- */
- public int get(char key);
-
- /**
- * @return Returns the value associated with the given key or the provided default value if the
- * key is not associated with any value.
- */
- public int getOrDefault(char key, int defaultValue);
-
- /**
- * Place a given key and value in the container.
- *
- * @return The value previously stored under the given key in the map is returned.
- */
- public int put(char key, int value);
-
- /**
- * If the specified key is not already associated with a value, associates it with the given
- * value.
- *
- * @return {@code true} if {@code key} did not exist and {@code value} was placed in the map,
- * {@code false} otherwise.
- */
- public default boolean putIfAbsent(char key, int value) {
- int keyIndex = indexOf(key);
- if (indexExists(keyIndex)) {
- return false;
- } else {
- indexInsert(keyIndex, key, value);
- return true;
- }
- }
-
- /**
- * Puts all keys from another container to this map, replacing the values of existing keys, if
- * such keys are present.
- *
- * @return Returns the number of keys added to the map as a result of this call (not previously
- * present in the map). Values of existing keys are overwritten.
- */
- public int putAll(CharIntAssociativeContainer container);
-
- /**
- * Puts all keys from an iterable cursor to this map, replacing the values of existing keys, if
- * such keys are present.
- *
- * @return Returns the number of keys added to the map as a result of this call (not previously
- * present in the map). Values of existing keys are overwritten.
- */
- public int putAll(Iterable extends CharIntCursor> iterable);
-
- /**
- * If key
exists, putValue
is inserted into the map, otherwise any
- * existing value is incremented by additionValue
.
- *
- * @param key The key of the value to adjust.
- * @param putValue The value to put if key
does not exist.
- * @param incrementValue The value to add to the existing value if key
exists.
- * @return Returns the current value associated with key
(after changes).
- */
- public int putOrAdd(char key, int putValue, int incrementValue);
-
- /**
- * An equivalent of calling
- *
- *
- * putOrAdd(key, additionValue, additionValue);
- *
- *
- * @param key The key of the value to adjust.
- * @param additionValue The value to put or add to the existing value if key
exists.
- * @return Returns the current value associated with key
(after changes).
- */
- public int addTo(char key, int additionValue);
-
- /**
- * Remove all values at the given key. The default value for the key type is returned if the value
- * does not exist in the map.
- */
- public int remove(char key);
-
- /**
- * Compares the specified object with this set for equality. Returns {@code true} if and only if
- * the specified object is also a {@link CharIntMap} and both objects contains exactly the same
- * key-value pairs.
- */
- public boolean equals(Object obj);
-
- /**
- * @return A hash code of elements stored in the map. The hash code is defined as a sum of hash
- * codes of keys and values stored within the set). Because sum is commutative, this ensures
- * that different order of elements in a set does not affect the hash code.
- */
- public int hashCode();
-
- /**
- * Returns a logical "index" of a given key that can be used to speed up follow-up value setters
- * or getters in certain scenarios (conditional logic).
- *
- * true
if the index corresponds to an existing key or false
- * otherwise. This is equivalent to checking whether the index is a positive value (existing
- * keys) or a negative value (non-existing keys).
- */
- public boolean indexExists(int index);
-
- /**
- * Returns the value associated with an existing key.
- *
- * @see #indexOf
- * @param index The index of an existing key.
- * @return Returns the value currently associated with the key.
- * @throws AssertionError If assertions are enabled and the index does not correspond to an
- * existing key.
- */
- public int indexGet(int index);
-
- /**
- * Replaces the value associated with an existing key and returns any previous value stored for
- * that key.
- *
- * @see #indexOf
- * @param index The index of an existing key.
- * @return Returns the previous value associated with the key.
- * @throws AssertionError If assertions are enabled and the index does not correspond to an
- * existing key.
- */
- public int indexReplace(int index, int newValue);
-
- /**
- * Inserts a key-value pair for a key that is not present in the map. This method may help in
- * avoiding double recalculation of the key's hash.
- *
- * @see #indexOf
- * @param index The index of a previously non-existing key, as returned from {@link #indexOf}.
- * @throws AssertionError If assertions are enabled and the index corresponds to an existing key.
- */
- public void indexInsert(int index, char key, int value);
-
- /**
- * Removes a key-value pair at an index previously acquired from {@link #indexOf}.
- *
- * @see #indexOf
- * @param index The index of the key to remove, as returned from {@link #indexOf}.
- * @return Returns the previous value associated with the key.
- * @throws AssertionError If assertions are enabled and the index does not correspond to an
- * existing key.
- */
- public int indexRemove(int index);
-
- /**
- * Clear all keys and values in the container.
- *
- * @see #release()
- */
- public void clear();
-
- /**
- * Removes all elements from the collection and additionally releases any internal buffers.
- * Typically, if the object is to be reused, a simple {@link #clear()} should be a better
- * alternative since it'll avoid reallocation.
- *
- * @see #clear()
- */
- public void release();
-
- /**
- * Visually depict the distribution of keys.
- *
- * @param characters The number of characters to "squeeze" the entire buffer into.
- * @return Returns a sequence of characters where '.' depicts an empty fragment of the internal
- * buffer and 'X' depicts full or nearly full capacity within the buffer's range and anything
- * between 1 and 9 is between.
- */
- public String visualizeKeyDistribution(int characters);
-}
diff --git a/sources/main/java/com/carrotsearch/hppc/CharLongAssociativeContainer.java b/sources/main/java/com/carrotsearch/hppc/CharLongAssociativeContainer.java
deleted file mode 100644
index 7999c340..00000000
--- a/sources/main/java/com/carrotsearch/hppc/CharLongAssociativeContainer.java
+++ /dev/null
@@ -1,105 +0,0 @@
-package com.carrotsearch.hppc;
-
-import com.carrotsearch.hppc.cursors.*;
-import com.carrotsearch.hppc.predicates.*;
-import com.carrotsearch.hppc.procedures.*;
-import java.util.Iterator;
-
-/**
- * An associative container from keys to (one or possibly more) values.
- *
- * @see CharContainer
- */
-@com.carrotsearch.hppc.Generated(
- date = "2024-06-04T15:20:17+0200",
- value = "KTypeVTypeAssociativeContainer.java")
-public interface CharLongAssociativeContainer extends Iterable
- * for (IntShortCursor c : intShortMap) {
- * System.out.println("index=" + c.index + " key=" + c.key + " value=" + c.value);
- * }
- *
- * index
field inside the cursor gives the internal index inside the
- * container's implementation. The interpretation of this index depends on to the container.
- */
- @Override
- public Iteratortrue
if this container has an association to a value for the given key.
- */
- public boolean containsKey(char key);
-
- /**
- * @return Returns the current size (number of assigned keys) in the container.
- */
- public int size();
-
- /**
- * @return Return true
if this hash map contains no assigned keys.
- */
- public boolean isEmpty();
-
- /**
- * Removes all keys (and associated values) present in a given container. An alias to:
- *
- *
- * keys().removeAll(container)
- *
- *
- * but with no additional overhead.
- *
- * @return Returns the number of elements actually removed as a result of this call.
- */
- public int removeAll(CharContainer container);
-
- /**
- * Removes all keys (and associated values) for which the predicate returns true
.
- *
- * @return Returns the number of elements actually removed as a result of this call.
- */
- public int removeAll(CharPredicate predicate);
-
- /**
- * Removes all keys (and associated values) for which the predicate returns true
.
- *
- * @return Returns the number of elements actually removed as a result of this call.
- */
- public int removeAll(CharLongPredicate predicate);
-
- /**
- * Applies a given procedure to all keys-value pairs in this container. Returns the argument (any
- * subclass of {@link CharLongProcedure}. This lets the caller call methods of the argument by
- * chaining the call (even if the argument is an anonymous type) to retrieve computed values.
- */
- public true
.
- */
- public char
to long
, implemented using open addressing with
- * linear probing for collision resolution.
- *
- * @see HPPC interfaces diagram
- */
-@com.carrotsearch.hppc.Generated(
- date = "2024-06-04T15:20:16+0200",
- value = "KTypeVTypeHashMap.java")
-public class CharLongHashMap implements CharLongMap, Preallocable, Cloneable, Accountable {
-
- /** The array holding keys. */
- public char[] keys;
-
- /** The array holding values. */
- public long[] values;
-
- /**
- * The number of stored keys (assigned key slots), excluding the special "empty" key, if any (use
- * {@link #size()} instead).
- *
- * @see #size()
- */
- protected int assigned;
-
- /** Mask for slot scans in {@link #keys}. */
- protected int mask;
-
- /** Expand (rehash) {@link #keys} when {@link #assigned} hits this value. */
- protected int resizeAt;
-
- /** Special treatment for the "empty slot" key marker. */
- protected boolean hasEmptyKey;
-
- /** The load factor for {@link #keys}. */
- protected double loadFactor;
-
- /** Seed used to ensure the hash iteration order is different from an iteration to another. */
- protected int iterationSeed;
-
- /** New instance with sane defaults. */
- public CharLongHashMap() {
- this(DEFAULT_EXPECTED_ELEMENTS);
- }
-
- /**
- * New instance with sane defaults.
- *
- * @param expectedElements The expected number of elements guaranteed not to cause buffer
- * expansion (inclusive).
- */
- public CharLongHashMap(int expectedElements) {
- this(expectedElements, DEFAULT_LOAD_FACTOR);
- }
-
- /**
- * New instance with the provided defaults.
- *
- * @param expectedElements The expected number of elements guaranteed not to cause a rehash
- * (inclusive).
- * @param loadFactor The load factor for internal buffers. Insane load factors (zero, full
- * capacity) are rejected by {@link #verifyLoadFactor(double)}.
- */
- public CharLongHashMap(int expectedElements, double loadFactor) {
- this.loadFactor = verifyLoadFactor(loadFactor);
- iterationSeed = HashContainers.nextIterationSeed();
- ensureCapacity(expectedElements);
- }
-
- /** Create a hash map from all key-value pairs of another container. */
- public CharLongHashMap(CharLongAssociativeContainer container) {
- this(container.size());
- putAll(container);
- }
-
- /** {@inheritDoc} */
- @Override
- public long put(char key, long value) {
- assert assigned < mask + 1;
-
- final int mask = this.mask;
- if (((key) == 0)) {
- long previousValue = hasEmptyKey ? values[mask + 1] : 0L;
- hasEmptyKey = true;
- values[mask + 1] = value;
- return previousValue;
- } else {
- final char[] keys = this.keys;
- int slot = hashKey(key) & mask;
-
- char existing;
- while (!((existing = keys[slot]) == 0)) {
- if (((key) == (existing))) {
- final long previousValue = values[slot];
- values[slot] = value;
- return previousValue;
- }
- slot = (slot + 1) & mask;
- }
-
- if (assigned == resizeAt) {
- allocateThenInsertThenRehash(slot, key, value);
- } else {
- keys[slot] = key;
- values[slot] = value;
- }
-
- assigned++;
- return 0L;
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public int putAll(CharLongAssociativeContainer container) {
- final int count = size();
- for (CharLongCursor c : container) {
- put(c.key, c.value);
- }
- return size() - count;
- }
-
- /** Puts all key/value pairs from a given iterable into this map. */
- @Override
- public int putAll(Iterable extends CharLongCursor> iterable) {
- final int count = size();
- for (CharLongCursor c : iterable) {
- put(c.key, c.value);
- }
- return size() - count;
- }
-
- /**
- * If key
exists, putValue
is inserted into the map, otherwise any
- * existing value is incremented by additionValue
.
- *
- * @param key The key of the value to adjust.
- * @param putValue The value to put if key
does not exist.
- * @param incrementValue The value to add to the existing value if key
exists.
- * @return Returns the current value associated with key
(after changes).
- */
- @Override
- public long putOrAdd(char key, long putValue, long incrementValue) {
- assert assigned < mask + 1;
-
- int keyIndex = indexOf(key);
- if (indexExists(keyIndex)) {
- putValue = ((long) ((values[keyIndex]) + (incrementValue)));
- indexReplace(keyIndex, putValue);
- } else {
- indexInsert(keyIndex, key, putValue);
- }
- return putValue;
- }
-
- /**
- * Adds incrementValue
to any existing value for the given key
or
- * inserts incrementValue
if key
did not previously exist.
- *
- * @param key The key of the value to adjust.
- * @param incrementValue The value to put or add to the existing value if key
exists.
- * @return Returns the current value associated with key
(after changes).
- */
- @Override
- public long addTo(char key, long incrementValue) {
- return putOrAdd(key, incrementValue, incrementValue);
- }
-
- /** {@inheritDoc} */
- @Override
- public long remove(char key) {
- final int mask = this.mask;
- if (((key) == 0)) {
- if (!hasEmptyKey) {
- return 0L;
- }
- hasEmptyKey = false;
- long previousValue = values[mask + 1];
- values[mask + 1] = 0L;
- return previousValue;
- } else {
- final char[] keys = this.keys;
- int slot = hashKey(key) & mask;
-
- char existing;
- while (!((existing = keys[slot]) == 0)) {
- if (((key) == (existing))) {
- final long previousValue = values[slot];
- shiftConflictingKeys(slot);
- return previousValue;
- }
- slot = (slot + 1) & mask;
- }
-
- return 0L;
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public int removeAll(CharContainer other) {
- final int before = size();
-
- // Try to iterate over the smaller set of values or
- // over the container that isn't implementing
- // efficient contains() lookup.
-
- if (other.size() >= size() && other instanceof CharLookupContainer) {
- if (hasEmptyKey && other.contains(((char) 0))) {
- hasEmptyKey = false;
- values[mask + 1] = 0L;
- }
-
- final char[] keys = this.keys;
- for (int slot = 0, max = this.mask; slot <= max; ) {
- char existing;
- if (!((existing = keys[slot]) == 0) && other.contains(existing)) {
- // Shift, do not increment slot.
- shiftConflictingKeys(slot);
- } else {
- slot++;
- }
- }
- } else {
- for (CharCursor c : other) {
- remove(c.value);
- }
- }
-
- return before - size();
- }
-
- /** {@inheritDoc} */
- @Override
- public int removeAll(CharLongPredicate predicate) {
- final int before = size();
-
- final int mask = this.mask;
-
- if (hasEmptyKey) {
- if (predicate.apply(((char) 0), values[mask + 1])) {
- hasEmptyKey = false;
- values[mask + 1] = 0L;
- }
- }
-
- final char[] keys = this.keys;
- final long[] values = this.values;
- for (int slot = 0; slot <= mask; ) {
- char existing;
- if (!((existing = keys[slot]) == 0) && predicate.apply(existing, values[slot])) {
- // Shift, do not increment slot.
- shiftConflictingKeys(slot);
- } else {
- slot++;
- }
- }
-
- return before - size();
- }
-
- /** {@inheritDoc} */
- @Override
- public int removeAll(CharPredicate predicate) {
- final int before = size();
-
- if (hasEmptyKey) {
- if (predicate.apply(((char) 0))) {
- hasEmptyKey = false;
- values[mask + 1] = 0L;
- }
- }
-
- final char[] keys = this.keys;
- for (int slot = 0, max = this.mask; slot <= max; ) {
- char existing;
- if (!((existing = keys[slot]) == 0) && predicate.apply(existing)) {
- // Shift, do not increment slot.
- shiftConflictingKeys(slot);
- } else {
- slot++;
- }
- }
-
- return before - size();
- }
-
- /** {@inheritDoc} */
- @Override
- public long get(char key) {
- if (((key) == 0)) {
- return hasEmptyKey ? values[mask + 1] : 0L;
- } else {
- final char[] keys = this.keys;
- final int mask = this.mask;
- int slot = hashKey(key) & mask;
-
- char existing;
- while (!((existing = keys[slot]) == 0)) {
- if (((key) == (existing))) {
- return values[slot];
- }
- slot = (slot + 1) & mask;
- }
-
- return 0L;
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public long getOrDefault(char key, long defaultValue) {
- if (((key) == 0)) {
- return hasEmptyKey ? values[mask + 1] : defaultValue;
- } else {
- final char[] keys = this.keys;
- final int mask = this.mask;
- int slot = hashKey(key) & mask;
-
- char existing;
- while (!((existing = keys[slot]) == 0)) {
- if (((key) == (existing))) {
- return values[slot];
- }
- slot = (slot + 1) & mask;
- }
-
- return defaultValue;
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean containsKey(char key) {
- if (((key) == 0)) {
- return hasEmptyKey;
- } else {
- final char[] keys = this.keys;
- final int mask = this.mask;
- int slot = hashKey(key) & mask;
-
- char existing;
- while (!((existing = keys[slot]) == 0)) {
- if (((key) == (existing))) {
- return true;
- }
- slot = (slot + 1) & mask;
- }
-
- return false;
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public int indexOf(char key) {
- final int mask = this.mask;
- if (((key) == 0)) {
- return hasEmptyKey ? mask + 1 : ~(mask + 1);
- } else {
- final char[] keys = this.keys;
- int slot = hashKey(key) & mask;
-
- char existing;
- while (!((existing = keys[slot]) == 0)) {
- if (((key) == (existing))) {
- return slot;
- }
- slot = (slot + 1) & mask;
- }
-
- return ~slot;
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean indexExists(int index) {
- assert index < 0 || (index >= 0 && index <= mask) || (index == mask + 1 && hasEmptyKey);
-
- return index >= 0;
- }
-
- /** {@inheritDoc} */
- @Override
- public long indexGet(int index) {
- assert index >= 0 : "The index must point at an existing key.";
- assert index <= mask || (index == mask + 1 && hasEmptyKey);
-
- return values[index];
- }
-
- /** {@inheritDoc} */
- @Override
- public long indexReplace(int index, long newValue) {
- assert index >= 0 : "The index must point at an existing key.";
- assert index <= mask || (index == mask + 1 && hasEmptyKey);
-
- long previousValue = values[index];
- values[index] = newValue;
- return previousValue;
- }
-
- /** {@inheritDoc} */
- @Override
- public void indexInsert(int index, char key, long value) {
- assert index < 0 : "The index must not point at an existing key.";
-
- index = ~index;
- if (((key) == 0)) {
- assert index == mask + 1;
- values[index] = value;
- hasEmptyKey = true;
- } else {
- assert ((keys[index]) == 0);
-
- if (assigned == resizeAt) {
- allocateThenInsertThenRehash(index, key, value);
- } else {
- keys[index] = key;
- values[index] = value;
- }
-
- assigned++;
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public long indexRemove(int index) {
- assert index >= 0 : "The index must point at an existing key.";
- assert index <= mask || (index == mask + 1 && hasEmptyKey);
-
- long previousValue = values[index];
- if (index > mask) {
- assert index == mask + 1;
- hasEmptyKey = false;
- values[index] = 0L;
- } else {
- shiftConflictingKeys(index);
- }
- return previousValue;
- }
-
- /** {@inheritDoc} */
- @Override
- public void clear() {
- assigned = 0;
- hasEmptyKey = false;
-
- Arrays.fill(keys, ((char) 0));
- }
-
- /** {@inheritDoc} */
- @Override
- public void release() {
- assigned = 0;
- hasEmptyKey = false;
-
- keys = null;
- values = null;
- ensureCapacity(Containers.DEFAULT_EXPECTED_ELEMENTS);
- }
-
- /** {@inheritDoc} */
- @Override
- public int size() {
- return assigned + (hasEmptyKey ? 1 : 0);
- }
-
- /** {@inheritDoc} */
- public boolean isEmpty() {
- return size() == 0;
- }
-
- /** {@inheritDoc} */
- @Override
- public int hashCode() {
- int h = hasEmptyKey ? 0xDEADBEEF : 0;
- for (CharLongCursor c : this) {
- h += BitMixer.mix(c.key) + BitMixer.mix(c.value);
- }
- return h;
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean equals(Object obj) {
- return (this == obj)
- || (obj != null && getClass() == obj.getClass() && equalElements(getClass().cast(obj)));
- }
-
- /** Return true if all keys of some other container exist in this container. */
- protected boolean equalElements(CharLongHashMap other) {
- if (other.size() != size()) {
- return false;
- }
-
- for (CharLongCursor c : other) {
- char key = c.key;
- if (!containsKey(key) || !((c.value) == (get(key)))) {
- return false;
- }
- }
-
- return true;
- }
-
- /**
- * Ensure this container can hold at least the given number of keys (entries) without resizing its
- * buffers.
- *
- * @param expectedElements The total number of keys, inclusive.
- */
- @Override
- public void ensureCapacity(int expectedElements) {
- if (expectedElements > resizeAt || keys == null) {
- final char[] prevKeys = this.keys;
- final long[] prevValues = this.values;
- allocateBuffers(minBufferSize(expectedElements, loadFactor));
- if (prevKeys != null && !isEmpty()) {
- rehash(prevKeys, prevValues);
- }
- }
- }
-
- @Override
- public long ramBytesAllocated() {
- // int: iterationSeed, assigned, mask, resizeAt
- // double: loadFactor
- // boolean: hasEmptyKey
- return RamUsageEstimator.NUM_BYTES_OBJECT_HEADER
- + 4 * Integer.BYTES
- + Double.BYTES
- + 1
- + RamUsageEstimator.shallowSizeOfArray(keys)
- + RamUsageEstimator.shallowSizeOfArray(values);
- }
-
- @Override
- public long ramBytesUsed() {
- // int: iterationSeed, assigned, mask, resizeAt
- // double: loadFactor
- // boolean: hasEmptyKey
- return RamUsageEstimator.NUM_BYTES_OBJECT_HEADER
- + 4 * Integer.BYTES
- + Double.BYTES
- + 1
- + RamUsageEstimator.shallowUsedSizeOfArray(keys, size())
- + RamUsageEstimator.shallowUsedSizeOfArray(values, size());
- }
-
- /**
- * Provides the next iteration seed used to build the iteration starting slot and offset
- * increment. This method does not need to be synchronized, what matters is that each thread gets
- * a sequence of varying seeds.
- */
- protected int nextIterationSeed() {
- return iterationSeed = BitMixer.mixPhi(iterationSeed);
- }
-
- /** An iterator implementation for {@link #iterator}. */
- private final class EntryIterator extends AbstractIteratorslot
.
- */
- protected void shiftConflictingKeys(int gapSlot) {
- final char[] keys = this.keys;
- final long[] values = this.values;
- final int mask = this.mask;
-
- // Perform shifts of conflicting keys to fill in the gap.
- int distance = 0;
- while (true) {
- final int slot = (gapSlot + (++distance)) & mask;
- final char existing = keys[slot];
- if (((existing) == 0)) {
- break;
- }
-
- final int idealSlot = hashKey(existing);
- final int shift = (slot - idealSlot) & mask;
- if (shift >= distance) {
- // Entry at this position was originally at or before the gap slot.
- // Move the conflict-shifted entry to the gap's position and repeat the procedure
- // for any entries to the right of the current position, treating it
- // as the new gap.
- keys[gapSlot] = existing;
- values[gapSlot] = values[slot];
- gapSlot = slot;
- distance = 0;
- }
- }
-
- // Mark the last found gap slot without a conflict as empty.
- keys[gapSlot] = ((char) 0);
- values[gapSlot] = 0L;
- assigned--;
- }
-}
diff --git a/sources/main/java/com/carrotsearch/hppc/CharLongMap.java b/sources/main/java/com/carrotsearch/hppc/CharLongMap.java
deleted file mode 100644
index fcbda2b4..00000000
--- a/sources/main/java/com/carrotsearch/hppc/CharLongMap.java
+++ /dev/null
@@ -1,205 +0,0 @@
-package com.carrotsearch.hppc;
-
-import com.carrotsearch.hppc.cursors.CharLongCursor;
-
-/** An associative container with unique binding from keys to a single value. */
-@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeVTypeMap.java")
-public interface CharLongMap extends CharLongAssociativeContainer {
- /**
- * @return Returns the value associated with the given key or the default value for the value
- * type, if the key is not associated with any value. For numeric value types, this default
- * value is 0, for object types it is {@code null}.
- */
- public long get(char key);
-
- /**
- * @return Returns the value associated with the given key or the provided default value if the
- * key is not associated with any value.
- */
- public long getOrDefault(char key, long defaultValue);
-
- /**
- * Place a given key and value in the container.
- *
- * @return The value previously stored under the given key in the map is returned.
- */
- public long put(char key, long value);
-
- /**
- * If the specified key is not already associated with a value, associates it with the given
- * value.
- *
- * @return {@code true} if {@code key} did not exist and {@code value} was placed in the map,
- * {@code false} otherwise.
- */
- public default boolean putIfAbsent(char key, long value) {
- int keyIndex = indexOf(key);
- if (indexExists(keyIndex)) {
- return false;
- } else {
- indexInsert(keyIndex, key, value);
- return true;
- }
- }
-
- /**
- * Puts all keys from another container to this map, replacing the values of existing keys, if
- * such keys are present.
- *
- * @return Returns the number of keys added to the map as a result of this call (not previously
- * present in the map). Values of existing keys are overwritten.
- */
- public int putAll(CharLongAssociativeContainer container);
-
- /**
- * Puts all keys from an iterable cursor to this map, replacing the values of existing keys, if
- * such keys are present.
- *
- * @return Returns the number of keys added to the map as a result of this call (not previously
- * present in the map). Values of existing keys are overwritten.
- */
- public int putAll(Iterable extends CharLongCursor> iterable);
-
- /**
- * If key
exists, putValue
is inserted into the map, otherwise any
- * existing value is incremented by additionValue
.
- *
- * @param key The key of the value to adjust.
- * @param putValue The value to put if key
does not exist.
- * @param incrementValue The value to add to the existing value if key
exists.
- * @return Returns the current value associated with key
(after changes).
- */
- public long putOrAdd(char key, long putValue, long incrementValue);
-
- /**
- * An equivalent of calling
- *
- *
- * putOrAdd(key, additionValue, additionValue);
- *
- *
- * @param key The key of the value to adjust.
- * @param additionValue The value to put or add to the existing value if key
exists.
- * @return Returns the current value associated with key
(after changes).
- */
- public long addTo(char key, long additionValue);
-
- /**
- * Remove all values at the given key. The default value for the key type is returned if the value
- * does not exist in the map.
- */
- public long remove(char key);
-
- /**
- * Compares the specified object with this set for equality. Returns {@code true} if and only if
- * the specified object is also a {@link CharLongMap} and both objects contains exactly the same
- * key-value pairs.
- */
- public boolean equals(Object obj);
-
- /**
- * @return A hash code of elements stored in the map. The hash code is defined as a sum of hash
- * codes of keys and values stored within the set). Because sum is commutative, this ensures
- * that different order of elements in a set does not affect the hash code.
- */
- public int hashCode();
-
- /**
- * Returns a logical "index" of a given key that can be used to speed up follow-up value setters
- * or getters in certain scenarios (conditional logic).
- *
- * true
if the index corresponds to an existing key or false
- * otherwise. This is equivalent to checking whether the index is a positive value (existing
- * keys) or a negative value (non-existing keys).
- */
- public boolean indexExists(int index);
-
- /**
- * Returns the value associated with an existing key.
- *
- * @see #indexOf
- * @param index The index of an existing key.
- * @return Returns the value currently associated with the key.
- * @throws AssertionError If assertions are enabled and the index does not correspond to an
- * existing key.
- */
- public long indexGet(int index);
-
- /**
- * Replaces the value associated with an existing key and returns any previous value stored for
- * that key.
- *
- * @see #indexOf
- * @param index The index of an existing key.
- * @return Returns the previous value associated with the key.
- * @throws AssertionError If assertions are enabled and the index does not correspond to an
- * existing key.
- */
- public long indexReplace(int index, long newValue);
-
- /**
- * Inserts a key-value pair for a key that is not present in the map. This method may help in
- * avoiding double recalculation of the key's hash.
- *
- * @see #indexOf
- * @param index The index of a previously non-existing key, as returned from {@link #indexOf}.
- * @throws AssertionError If assertions are enabled and the index corresponds to an existing key.
- */
- public void indexInsert(int index, char key, long value);
-
- /**
- * Removes a key-value pair at an index previously acquired from {@link #indexOf}.
- *
- * @see #indexOf
- * @param index The index of the key to remove, as returned from {@link #indexOf}.
- * @return Returns the previous value associated with the key.
- * @throws AssertionError If assertions are enabled and the index does not correspond to an
- * existing key.
- */
- public long indexRemove(int index);
-
- /**
- * Clear all keys and values in the container.
- *
- * @see #release()
- */
- public void clear();
-
- /**
- * Removes all elements from the collection and additionally releases any internal buffers.
- * Typically, if the object is to be reused, a simple {@link #clear()} should be a better
- * alternative since it'll avoid reallocation.
- *
- * @see #clear()
- */
- public void release();
-
- /**
- * Visually depict the distribution of keys.
- *
- * @param characters The number of characters to "squeeze" the entire buffer into.
- * @return Returns a sequence of characters where '.' depicts an empty fragment of the internal
- * buffer and 'X' depicts full or nearly full capacity within the buffer's range and anything
- * between 1 and 9 is between.
- */
- public String visualizeKeyDistribution(int characters);
-}
diff --git a/sources/main/java/com/carrotsearch/hppc/CharLookupContainer.java b/sources/main/java/com/carrotsearch/hppc/CharLookupContainer.java
deleted file mode 100644
index 3e2fd0a4..00000000
--- a/sources/main/java/com/carrotsearch/hppc/CharLookupContainer.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package com.carrotsearch.hppc;
-
-/**
- * Marker interface for containers that can check if they contain a given object in at least time
- * O(log n)
and ideally in amortized constant time O(1)
.
- */
-@com.carrotsearch.hppc.Generated(
- date = "2024-06-04T15:20:17+0200",
- value = "KTypeLookupContainer.java")
-public interface CharLookupContainer extends CharContainer {
- public boolean contains(char e);
-}
diff --git a/sources/main/java/com/carrotsearch/hppc/CharObjectAssociativeContainer.java b/sources/main/java/com/carrotsearch/hppc/CharObjectAssociativeContainer.java
deleted file mode 100644
index 806efa68..00000000
--- a/sources/main/java/com/carrotsearch/hppc/CharObjectAssociativeContainer.java
+++ /dev/null
@@ -1,105 +0,0 @@
-package com.carrotsearch.hppc;
-
-import com.carrotsearch.hppc.cursors.*;
-import com.carrotsearch.hppc.predicates.*;
-import com.carrotsearch.hppc.procedures.*;
-import java.util.Iterator;
-
-/**
- * An associative container from keys to (one or possibly more) values.
- *
- * @see CharContainer
- */
-@com.carrotsearch.hppc.Generated(
- date = "2024-06-04T15:20:17+0200",
- value = "KTypeVTypeAssociativeContainer.java")
-public interface CharObjectAssociativeContainer
- * for (IntShortCursor c : intShortMap) {
- * System.out.println("index=" + c.index + " key=" + c.key + " value=" + c.value);
- * }
- *
- * index
field inside the cursor gives the internal index inside the
- * container's implementation. The interpretation of this index depends on to the container.
- */
- @Override
- public Iteratortrue
if this container has an association to a value for the given key.
- */
- public boolean containsKey(char key);
-
- /**
- * @return Returns the current size (number of assigned keys) in the container.
- */
- public int size();
-
- /**
- * @return Return true
if this hash map contains no assigned keys.
- */
- public boolean isEmpty();
-
- /**
- * Removes all keys (and associated values) present in a given container. An alias to:
- *
- *
- * keys().removeAll(container)
- *
- *
- * but with no additional overhead.
- *
- * @return Returns the number of elements actually removed as a result of this call.
- */
- public int removeAll(CharContainer container);
-
- /**
- * Removes all keys (and associated values) for which the predicate returns true
.
- *
- * @return Returns the number of elements actually removed as a result of this call.
- */
- public int removeAll(CharPredicate predicate);
-
- /**
- * Removes all keys (and associated values) for which the predicate returns true
.
- *
- * @return Returns the number of elements actually removed as a result of this call.
- */
- public int removeAll(CharObjectPredicate super VType> predicate);
-
- /**
- * Applies a given procedure to all keys-value pairs in this container. Returns the argument (any
- * subclass of {@link CharObjectProcedure}. This lets the caller call methods of the argument by
- * chaining the call (even if the argument is an anonymous type) to retrieve computed values.
- */
- public true
.
- */
- public char
to Object
, implemented using open addressing with
- * linear probing for collision resolution. Supports null values.
- *
- * @see HPPC interfaces diagram
- */
-@SuppressWarnings("unchecked")
-@com.carrotsearch.hppc.Generated(
- date = "2024-06-04T15:20:16+0200",
- value = "KTypeVTypeHashMap.java")
-public class CharObjectHashMapslot
.
- */
- protected void shiftConflictingKeys(int gapSlot) {
- final char[] keys = this.keys;
- final VType[] values = (VType[]) this.values;
- final int mask = this.mask;
-
- // Perform shifts of conflicting keys to fill in the gap.
- int distance = 0;
- while (true) {
- final int slot = (gapSlot + (++distance)) & mask;
- final char existing = keys[slot];
- if (((existing) == 0)) {
- break;
- }
-
- final int idealSlot = hashKey(existing);
- final int shift = (slot - idealSlot) & mask;
- if (shift >= distance) {
- // Entry at this position was originally at or before the gap slot.
- // Move the conflict-shifted entry to the gap's position and repeat the procedure
- // for any entries to the right of the current position, treating it
- // as the new gap.
- keys[gapSlot] = existing;
- values[gapSlot] = values[slot];
- gapSlot = slot;
- distance = 0;
- }
- }
-
- // Mark the last found gap slot without a conflict as empty.
- keys[gapSlot] = ((char) 0);
- values[gapSlot] = null;
- assigned--;
- }
-}
diff --git a/sources/main/java/com/carrotsearch/hppc/CharObjectMap.java b/sources/main/java/com/carrotsearch/hppc/CharObjectMap.java
deleted file mode 100644
index 6a1004df..00000000
--- a/sources/main/java/com/carrotsearch/hppc/CharObjectMap.java
+++ /dev/null
@@ -1,181 +0,0 @@
-package com.carrotsearch.hppc;
-
-import com.carrotsearch.hppc.cursors.CharObjectCursor;
-
-/** An associative container with unique binding from keys to a single value. */
-@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeVTypeMap.java")
-public interface CharObjectMaptrue
if the index corresponds to an existing key or false
- * otherwise. This is equivalent to checking whether the index is a positive value (existing
- * keys) or a negative value (non-existing keys).
- */
- public boolean indexExists(int index);
-
- /**
- * Returns the value associated with an existing key.
- *
- * @see #indexOf
- * @param index The index of an existing key.
- * @return Returns the value currently associated with the key.
- * @throws AssertionError If assertions are enabled and the index does not correspond to an
- * existing key.
- */
- public VType indexGet(int index);
-
- /**
- * Replaces the value associated with an existing key and returns any previous value stored for
- * that key.
- *
- * @see #indexOf
- * @param index The index of an existing key.
- * @return Returns the previous value associated with the key.
- * @throws AssertionError If assertions are enabled and the index does not correspond to an
- * existing key.
- */
- public VType indexReplace(int index, VType newValue);
-
- /**
- * Inserts a key-value pair for a key that is not present in the map. This method may help in
- * avoiding double recalculation of the key's hash.
- *
- * @see #indexOf
- * @param index The index of a previously non-existing key, as returned from {@link #indexOf}.
- * @throws AssertionError If assertions are enabled and the index corresponds to an existing key.
- */
- public void indexInsert(int index, char key, VType value);
-
- /**
- * Removes a key-value pair at an index previously acquired from {@link #indexOf}.
- *
- * @see #indexOf
- * @param index The index of the key to remove, as returned from {@link #indexOf}.
- * @return Returns the previous value associated with the key.
- * @throws AssertionError If assertions are enabled and the index does not correspond to an
- * existing key.
- */
- public VType indexRemove(int index);
-
- /**
- * Clear all keys and values in the container.
- *
- * @see #release()
- */
- public void clear();
-
- /**
- * Removes all elements from the collection and additionally releases any internal buffers.
- * Typically, if the object is to be reused, a simple {@link #clear()} should be a better
- * alternative since it'll avoid reallocation.
- *
- * @see #clear()
- */
- public void release();
-
- /**
- * Visually depict the distribution of keys.
- *
- * @param characters The number of characters to "squeeze" the entire buffer into.
- * @return Returns a sequence of characters where '.' depicts an empty fragment of the internal
- * buffer and 'X' depicts full or nearly full capacity within the buffer's range and anything
- * between 1 and 9 is between.
- */
- public String visualizeKeyDistribution(int characters);
-}
diff --git a/sources/main/java/com/carrotsearch/hppc/CharSet.java b/sources/main/java/com/carrotsearch/hppc/CharSet.java
deleted file mode 100644
index a9740eac..00000000
--- a/sources/main/java/com/carrotsearch/hppc/CharSet.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package com.carrotsearch.hppc;
-
-/** A set of char
s. */
-@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeSet.java")
-public interface CharSet extends CharCollection {
- /**
- * Adds k
to the set.
- *
- * @return Returns true
if this element was not part of the set before. Returns
- * false
if an equal element is already part of the set, does not replace the
- * existing element with the argument.
- */
- public boolean add(char k);
-
- /**
- * Visually depict the distribution of keys.
- *
- * @param characters The number of characters to "squeeze" the entire buffer into.
- * @return Returns a sequence of characters where '.' depicts an empty fragment of the internal
- * buffer and 'X' depicts full or nearly full capacity within the buffer's range and anything
- * between 1 and 9 is between.
- */
- public String visualizeKeyDistribution(int characters);
-
- /**
- * Adds all elements from the given {@link CharContainer} to this set.
- *
- * @return Returns the number of elements actually added as a result of this call (not previously
- * present in the set).
- * @since 0.9.1
- */
- public int addAll(CharContainer container);
-}
diff --git a/sources/main/java/com/carrotsearch/hppc/CharShortAssociativeContainer.java b/sources/main/java/com/carrotsearch/hppc/CharShortAssociativeContainer.java
deleted file mode 100644
index 66f6c444..00000000
--- a/sources/main/java/com/carrotsearch/hppc/CharShortAssociativeContainer.java
+++ /dev/null
@@ -1,105 +0,0 @@
-package com.carrotsearch.hppc;
-
-import com.carrotsearch.hppc.cursors.*;
-import com.carrotsearch.hppc.predicates.*;
-import com.carrotsearch.hppc.procedures.*;
-import java.util.Iterator;
-
-/**
- * An associative container from keys to (one or possibly more) values.
- *
- * @see CharContainer
- */
-@com.carrotsearch.hppc.Generated(
- date = "2024-06-04T15:20:17+0200",
- value = "KTypeVTypeAssociativeContainer.java")
-public interface CharShortAssociativeContainer extends Iterable
- * for (IntShortCursor c : intShortMap) {
- * System.out.println("index=" + c.index + " key=" + c.key + " value=" + c.value);
- * }
- *
- * index
field inside the cursor gives the internal index inside the
- * container's implementation. The interpretation of this index depends on to the container.
- */
- @Override
- public Iteratortrue
if this container has an association to a value for the given key.
- */
- public boolean containsKey(char key);
-
- /**
- * @return Returns the current size (number of assigned keys) in the container.
- */
- public int size();
-
- /**
- * @return Return true
if this hash map contains no assigned keys.
- */
- public boolean isEmpty();
-
- /**
- * Removes all keys (and associated values) present in a given container. An alias to:
- *
- *
- * keys().removeAll(container)
- *
- *
- * but with no additional overhead.
- *
- * @return Returns the number of elements actually removed as a result of this call.
- */
- public int removeAll(CharContainer container);
-
- /**
- * Removes all keys (and associated values) for which the predicate returns true
.
- *
- * @return Returns the number of elements actually removed as a result of this call.
- */
- public int removeAll(CharPredicate predicate);
-
- /**
- * Removes all keys (and associated values) for which the predicate returns true
.
- *
- * @return Returns the number of elements actually removed as a result of this call.
- */
- public int removeAll(CharShortPredicate predicate);
-
- /**
- * Applies a given procedure to all keys-value pairs in this container. Returns the argument (any
- * subclass of {@link CharShortProcedure}. This lets the caller call methods of the argument by
- * chaining the call (even if the argument is an anonymous type) to retrieve computed values.
- */
- public true
.
- */
- public char
to short
, implemented using open addressing with
- * linear probing for collision resolution.
- *
- * @see HPPC interfaces diagram
- */
-@com.carrotsearch.hppc.Generated(
- date = "2024-06-04T15:20:16+0200",
- value = "KTypeVTypeHashMap.java")
-public class CharShortHashMap implements CharShortMap, Preallocable, Cloneable, Accountable {
-
- /** The array holding keys. */
- public char[] keys;
-
- /** The array holding values. */
- public short[] values;
-
- /**
- * The number of stored keys (assigned key slots), excluding the special "empty" key, if any (use
- * {@link #size()} instead).
- *
- * @see #size()
- */
- protected int assigned;
-
- /** Mask for slot scans in {@link #keys}. */
- protected int mask;
-
- /** Expand (rehash) {@link #keys} when {@link #assigned} hits this value. */
- protected int resizeAt;
-
- /** Special treatment for the "empty slot" key marker. */
- protected boolean hasEmptyKey;
-
- /** The load factor for {@link #keys}. */
- protected double loadFactor;
-
- /** Seed used to ensure the hash iteration order is different from an iteration to another. */
- protected int iterationSeed;
-
- /** New instance with sane defaults. */
- public CharShortHashMap() {
- this(DEFAULT_EXPECTED_ELEMENTS);
- }
-
- /**
- * New instance with sane defaults.
- *
- * @param expectedElements The expected number of elements guaranteed not to cause buffer
- * expansion (inclusive).
- */
- public CharShortHashMap(int expectedElements) {
- this(expectedElements, DEFAULT_LOAD_FACTOR);
- }
-
- /**
- * New instance with the provided defaults.
- *
- * @param expectedElements The expected number of elements guaranteed not to cause a rehash
- * (inclusive).
- * @param loadFactor The load factor for internal buffers. Insane load factors (zero, full
- * capacity) are rejected by {@link #verifyLoadFactor(double)}.
- */
- public CharShortHashMap(int expectedElements, double loadFactor) {
- this.loadFactor = verifyLoadFactor(loadFactor);
- iterationSeed = HashContainers.nextIterationSeed();
- ensureCapacity(expectedElements);
- }
-
- /** Create a hash map from all key-value pairs of another container. */
- public CharShortHashMap(CharShortAssociativeContainer container) {
- this(container.size());
- putAll(container);
- }
-
- /** {@inheritDoc} */
- @Override
- public short put(char key, short value) {
- assert assigned < mask + 1;
-
- final int mask = this.mask;
- if (((key) == 0)) {
- short previousValue = hasEmptyKey ? values[mask + 1] : ((short) 0);
- hasEmptyKey = true;
- values[mask + 1] = value;
- return previousValue;
- } else {
- final char[] keys = this.keys;
- int slot = hashKey(key) & mask;
-
- char existing;
- while (!((existing = keys[slot]) == 0)) {
- if (((key) == (existing))) {
- final short previousValue = values[slot];
- values[slot] = value;
- return previousValue;
- }
- slot = (slot + 1) & mask;
- }
-
- if (assigned == resizeAt) {
- allocateThenInsertThenRehash(slot, key, value);
- } else {
- keys[slot] = key;
- values[slot] = value;
- }
-
- assigned++;
- return ((short) 0);
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public int putAll(CharShortAssociativeContainer container) {
- final int count = size();
- for (CharShortCursor c : container) {
- put(c.key, c.value);
- }
- return size() - count;
- }
-
- /** Puts all key/value pairs from a given iterable into this map. */
- @Override
- public int putAll(Iterable extends CharShortCursor> iterable) {
- final int count = size();
- for (CharShortCursor c : iterable) {
- put(c.key, c.value);
- }
- return size() - count;
- }
-
- /**
- * If key
exists, putValue
is inserted into the map, otherwise any
- * existing value is incremented by additionValue
.
- *
- * @param key The key of the value to adjust.
- * @param putValue The value to put if key
does not exist.
- * @param incrementValue The value to add to the existing value if key
exists.
- * @return Returns the current value associated with key
(after changes).
- */
- @Override
- public short putOrAdd(char key, short putValue, short incrementValue) {
- assert assigned < mask + 1;
-
- int keyIndex = indexOf(key);
- if (indexExists(keyIndex)) {
- putValue = ((short) ((values[keyIndex]) + (incrementValue)));
- indexReplace(keyIndex, putValue);
- } else {
- indexInsert(keyIndex, key, putValue);
- }
- return putValue;
- }
-
- /**
- * Adds incrementValue
to any existing value for the given key
or
- * inserts incrementValue
if key
did not previously exist.
- *
- * @param key The key of the value to adjust.
- * @param incrementValue The value to put or add to the existing value if key
exists.
- * @return Returns the current value associated with key
(after changes).
- */
- @Override
- public short addTo(char key, short incrementValue) {
- return putOrAdd(key, incrementValue, incrementValue);
- }
-
- /** {@inheritDoc} */
- @Override
- public short remove(char key) {
- final int mask = this.mask;
- if (((key) == 0)) {
- if (!hasEmptyKey) {
- return ((short) 0);
- }
- hasEmptyKey = false;
- short previousValue = values[mask + 1];
- values[mask + 1] = ((short) 0);
- return previousValue;
- } else {
- final char[] keys = this.keys;
- int slot = hashKey(key) & mask;
-
- char existing;
- while (!((existing = keys[slot]) == 0)) {
- if (((key) == (existing))) {
- final short previousValue = values[slot];
- shiftConflictingKeys(slot);
- return previousValue;
- }
- slot = (slot + 1) & mask;
- }
-
- return ((short) 0);
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public int removeAll(CharContainer other) {
- final int before = size();
-
- // Try to iterate over the smaller set of values or
- // over the container that isn't implementing
- // efficient contains() lookup.
-
- if (other.size() >= size() && other instanceof CharLookupContainer) {
- if (hasEmptyKey && other.contains(((char) 0))) {
- hasEmptyKey = false;
- values[mask + 1] = ((short) 0);
- }
-
- final char[] keys = this.keys;
- for (int slot = 0, max = this.mask; slot <= max; ) {
- char existing;
- if (!((existing = keys[slot]) == 0) && other.contains(existing)) {
- // Shift, do not increment slot.
- shiftConflictingKeys(slot);
- } else {
- slot++;
- }
- }
- } else {
- for (CharCursor c : other) {
- remove(c.value);
- }
- }
-
- return before - size();
- }
-
- /** {@inheritDoc} */
- @Override
- public int removeAll(CharShortPredicate predicate) {
- final int before = size();
-
- final int mask = this.mask;
-
- if (hasEmptyKey) {
- if (predicate.apply(((char) 0), values[mask + 1])) {
- hasEmptyKey = false;
- values[mask + 1] = ((short) 0);
- }
- }
-
- final char[] keys = this.keys;
- final short[] values = this.values;
- for (int slot = 0; slot <= mask; ) {
- char existing;
- if (!((existing = keys[slot]) == 0) && predicate.apply(existing, values[slot])) {
- // Shift, do not increment slot.
- shiftConflictingKeys(slot);
- } else {
- slot++;
- }
- }
-
- return before - size();
- }
-
- /** {@inheritDoc} */
- @Override
- public int removeAll(CharPredicate predicate) {
- final int before = size();
-
- if (hasEmptyKey) {
- if (predicate.apply(((char) 0))) {
- hasEmptyKey = false;
- values[mask + 1] = ((short) 0);
- }
- }
-
- final char[] keys = this.keys;
- for (int slot = 0, max = this.mask; slot <= max; ) {
- char existing;
- if (!((existing = keys[slot]) == 0) && predicate.apply(existing)) {
- // Shift, do not increment slot.
- shiftConflictingKeys(slot);
- } else {
- slot++;
- }
- }
-
- return before - size();
- }
-
- /** {@inheritDoc} */
- @Override
- public short get(char key) {
- if (((key) == 0)) {
- return hasEmptyKey ? values[mask + 1] : ((short) 0);
- } else {
- final char[] keys = this.keys;
- final int mask = this.mask;
- int slot = hashKey(key) & mask;
-
- char existing;
- while (!((existing = keys[slot]) == 0)) {
- if (((key) == (existing))) {
- return values[slot];
- }
- slot = (slot + 1) & mask;
- }
-
- return ((short) 0);
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public short getOrDefault(char key, short defaultValue) {
- if (((key) == 0)) {
- return hasEmptyKey ? values[mask + 1] : defaultValue;
- } else {
- final char[] keys = this.keys;
- final int mask = this.mask;
- int slot = hashKey(key) & mask;
-
- char existing;
- while (!((existing = keys[slot]) == 0)) {
- if (((key) == (existing))) {
- return values[slot];
- }
- slot = (slot + 1) & mask;
- }
-
- return defaultValue;
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean containsKey(char key) {
- if (((key) == 0)) {
- return hasEmptyKey;
- } else {
- final char[] keys = this.keys;
- final int mask = this.mask;
- int slot = hashKey(key) & mask;
-
- char existing;
- while (!((existing = keys[slot]) == 0)) {
- if (((key) == (existing))) {
- return true;
- }
- slot = (slot + 1) & mask;
- }
-
- return false;
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public int indexOf(char key) {
- final int mask = this.mask;
- if (((key) == 0)) {
- return hasEmptyKey ? mask + 1 : ~(mask + 1);
- } else {
- final char[] keys = this.keys;
- int slot = hashKey(key) & mask;
-
- char existing;
- while (!((existing = keys[slot]) == 0)) {
- if (((key) == (existing))) {
- return slot;
- }
- slot = (slot + 1) & mask;
- }
-
- return ~slot;
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean indexExists(int index) {
- assert index < 0 || (index >= 0 && index <= mask) || (index == mask + 1 && hasEmptyKey);
-
- return index >= 0;
- }
-
- /** {@inheritDoc} */
- @Override
- public short indexGet(int index) {
- assert index >= 0 : "The index must point at an existing key.";
- assert index <= mask || (index == mask + 1 && hasEmptyKey);
-
- return values[index];
- }
-
- /** {@inheritDoc} */
- @Override
- public short indexReplace(int index, short newValue) {
- assert index >= 0 : "The index must point at an existing key.";
- assert index <= mask || (index == mask + 1 && hasEmptyKey);
-
- short previousValue = values[index];
- values[index] = newValue;
- return previousValue;
- }
-
- /** {@inheritDoc} */
- @Override
- public void indexInsert(int index, char key, short value) {
- assert index < 0 : "The index must not point at an existing key.";
-
- index = ~index;
- if (((key) == 0)) {
- assert index == mask + 1;
- values[index] = value;
- hasEmptyKey = true;
- } else {
- assert ((keys[index]) == 0);
-
- if (assigned == resizeAt) {
- allocateThenInsertThenRehash(index, key, value);
- } else {
- keys[index] = key;
- values[index] = value;
- }
-
- assigned++;
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public short indexRemove(int index) {
- assert index >= 0 : "The index must point at an existing key.";
- assert index <= mask || (index == mask + 1 && hasEmptyKey);
-
- short previousValue = values[index];
- if (index > mask) {
- assert index == mask + 1;
- hasEmptyKey = false;
- values[index] = ((short) 0);
- } else {
- shiftConflictingKeys(index);
- }
- return previousValue;
- }
-
- /** {@inheritDoc} */
- @Override
- public void clear() {
- assigned = 0;
- hasEmptyKey = false;
-
- Arrays.fill(keys, ((char) 0));
- }
-
- /** {@inheritDoc} */
- @Override
- public void release() {
- assigned = 0;
- hasEmptyKey = false;
-
- keys = null;
- values = null;
- ensureCapacity(Containers.DEFAULT_EXPECTED_ELEMENTS);
- }
-
- /** {@inheritDoc} */
- @Override
- public int size() {
- return assigned + (hasEmptyKey ? 1 : 0);
- }
-
- /** {@inheritDoc} */
- public boolean isEmpty() {
- return size() == 0;
- }
-
- /** {@inheritDoc} */
- @Override
- public int hashCode() {
- int h = hasEmptyKey ? 0xDEADBEEF : 0;
- for (CharShortCursor c : this) {
- h += BitMixer.mix(c.key) + BitMixer.mix(c.value);
- }
- return h;
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean equals(Object obj) {
- return (this == obj)
- || (obj != null && getClass() == obj.getClass() && equalElements(getClass().cast(obj)));
- }
-
- /** Return true if all keys of some other container exist in this container. */
- protected boolean equalElements(CharShortHashMap other) {
- if (other.size() != size()) {
- return false;
- }
-
- for (CharShortCursor c : other) {
- char key = c.key;
- if (!containsKey(key) || !((c.value) == (get(key)))) {
- return false;
- }
- }
-
- return true;
- }
-
- /**
- * Ensure this container can hold at least the given number of keys (entries) without resizing its
- * buffers.
- *
- * @param expectedElements The total number of keys, inclusive.
- */
- @Override
- public void ensureCapacity(int expectedElements) {
- if (expectedElements > resizeAt || keys == null) {
- final char[] prevKeys = this.keys;
- final short[] prevValues = this.values;
- allocateBuffers(minBufferSize(expectedElements, loadFactor));
- if (prevKeys != null && !isEmpty()) {
- rehash(prevKeys, prevValues);
- }
- }
- }
-
- @Override
- public long ramBytesAllocated() {
- // int: iterationSeed, assigned, mask, resizeAt
- // double: loadFactor
- // boolean: hasEmptyKey
- return RamUsageEstimator.NUM_BYTES_OBJECT_HEADER
- + 4 * Integer.BYTES
- + Double.BYTES
- + 1
- + RamUsageEstimator.shallowSizeOfArray(keys)
- + RamUsageEstimator.shallowSizeOfArray(values);
- }
-
- @Override
- public long ramBytesUsed() {
- // int: iterationSeed, assigned, mask, resizeAt
- // double: loadFactor
- // boolean: hasEmptyKey
- return RamUsageEstimator.NUM_BYTES_OBJECT_HEADER
- + 4 * Integer.BYTES
- + Double.BYTES
- + 1
- + RamUsageEstimator.shallowUsedSizeOfArray(keys, size())
- + RamUsageEstimator.shallowUsedSizeOfArray(values, size());
- }
-
- /**
- * Provides the next iteration seed used to build the iteration starting slot and offset
- * increment. This method does not need to be synchronized, what matters is that each thread gets
- * a sequence of varying seeds.
- */
- protected int nextIterationSeed() {
- return iterationSeed = BitMixer.mixPhi(iterationSeed);
- }
-
- /** An iterator implementation for {@link #iterator}. */
- private final class EntryIterator extends AbstractIterator